mirror of
https://github.com/MuntashirAkon/android-debloat-list.git
synced 2025-10-10 06:57:23 +08:00
Add lint checker
This commit is contained in:
207
scripts/lint.php
Normal file
207
scripts/lint.php
Normal file
@@ -0,0 +1,207 @@
|
||||
<?php
|
||||
/* SPDX-License-Identifier: AGPL-3.0-or-later */
|
||||
|
||||
const SUPPORTED_REMOVAL_TYPES = ['delete', 'replace', 'caution', 'unsafe'];
|
||||
const SUPPORTED_TAGS = [];
|
||||
const REPO_DIR = __DIR__ . "/..";
|
||||
const SUGGESTIONS_DIR = REPO_DIR . '/suggestions';
|
||||
const LINT_DIR = __DIR__ . "/../build";
|
||||
|
||||
if (!file_exists(LINT_DIR)) {
|
||||
mkdir(LINT_DIR, 0777, true);
|
||||
}
|
||||
|
||||
$lint_writer = fopen(LINT_DIR . "/lint-results.txt", "w");
|
||||
|
||||
// START MAIN
|
||||
|
||||
$error_count = 0;
|
||||
foreach (scandir(REPO_DIR) as $filename) {
|
||||
if (!str_ends_with($filename, ".json")) {
|
||||
continue;
|
||||
}
|
||||
$file = REPO_DIR . '/' . $filename;
|
||||
$type = substr($filename, 0, -5);
|
||||
$list = json_decode(file_get_contents($file), true);
|
||||
if ($list === null) {
|
||||
fprintf($lint_writer, "Malformed file: $file\n");
|
||||
++$error_count;
|
||||
continue;
|
||||
} else fprintf($lint_writer, "Adding $filename\n");
|
||||
foreach ($list as $item) {
|
||||
$error_count += validate_bloatware_item($item);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (scandir(SUGGESTIONS_DIR) as $filename) {
|
||||
if (!str_ends_with($filename, ".json")) {
|
||||
continue;
|
||||
}
|
||||
$suggestion_file = SUGGESTIONS_DIR . '/' . $filename;
|
||||
$suggestion_id = substr($filename, 0, -5);
|
||||
$single_suggestion_list = json_decode(file_get_contents($suggestion_file), true);
|
||||
if ($single_suggestion_list === null) {
|
||||
fprintf($lint_writer, "Malformed file: $suggestion_file\n");
|
||||
++$error_count;
|
||||
continue;
|
||||
} else fprintf($lint_writer, "Adding $filename\n");
|
||||
foreach ($single_suggestion_list as $suggestion) {
|
||||
$error_count += validate_suggestion_item($suggestion);
|
||||
}
|
||||
}
|
||||
|
||||
if ($error_count != 0) {
|
||||
$msg = "\n$error_count ERRORS.\n";
|
||||
fprintf($lint_writer, $msg);
|
||||
fprintf(STDERR, $msg);
|
||||
exit(1);
|
||||
} else {
|
||||
$msg = "No errors.\n";
|
||||
fprintf($lint_writer, $msg);
|
||||
fprintf(STDERR, $msg);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// END MAIN
|
||||
|
||||
function validate_bloatware_item(array $item): int {
|
||||
global $lint_writer;
|
||||
$error_count = 0;
|
||||
// `id` is a string
|
||||
if (gettype($item['id']) != 'string') {
|
||||
fprintf($lint_writer, "Expected `id` field to be a string, found: " . gettype($item['id']) . "\n");
|
||||
++$error_count;
|
||||
}
|
||||
// `label` is an optional string
|
||||
if (isset($item['label']) && gettype($item['label']) != 'string') {
|
||||
fprintf($lint_writer, "{$item['id']}: Expected `label` field to be a string, found: " . gettype($item['label']) . "\n");
|
||||
++$error_count;
|
||||
}
|
||||
// `dependencies` is an optional string[]
|
||||
if (isset($item['dependencies'])) {
|
||||
if (gettype($item['dependencies']) != 'array') {
|
||||
fprintf($lint_writer, "{$item['id']}: Expected `dependencies` field to be an array, found: " . gettype($item['dependencies']) . "\n");
|
||||
++$error_count;
|
||||
} else {
|
||||
foreach ($item['dependencies'] as $dependency) {
|
||||
if (gettype($dependency) != 'string') {
|
||||
fprintf($lint_writer, "{$item['id']}: Expected `dependencies` items to be a string, found: " . gettype($dependency) . "\n");
|
||||
++$error_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// `required_by` is an optional string[]
|
||||
if (isset($item['required_by'])) {
|
||||
if (gettype($item['required_by']) != 'array') {
|
||||
fprintf($lint_writer, "{$item['id']}: Expected `required_by` field to be an array, found: " . gettype($item['required_by']) . "\n");
|
||||
++$error_count;
|
||||
} else {
|
||||
foreach ($item['required_by'] as $required_by) {
|
||||
if (gettype($required_by) != 'string') {
|
||||
fprintf($lint_writer, "{$item['id']}: Expected `required_by` items to be a string, found: " . gettype($required_by) . "\n");
|
||||
++$error_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// `tags` is an optional string[]
|
||||
if (isset($item['tags'])) {
|
||||
if (gettype($item['tags']) != 'array') {
|
||||
fprintf($lint_writer, "{$item['id']}: Expected `tags` field to be an array, found: " . gettype($item['tags']) . "\n");
|
||||
++$error_count;
|
||||
} else {
|
||||
foreach ($item['tags'] as $tag) {
|
||||
if (gettype($tag) != 'string') {
|
||||
fprintf($lint_writer, "{$item['id']}: Expected `tags` items to be a string, found: " . gettype($tag) . "\n");
|
||||
++$error_count;
|
||||
} else if (!in_array($tag, SUPPORTED_TAGS)) {
|
||||
fprintf($lint_writer, "{$item['id']}: Invalid `tag`: $tag\n");
|
||||
++$error_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// `description` is a string
|
||||
if (gettype($item['description']) != 'string') {
|
||||
fprintf($lint_writer, "{$item['id']}: Expected `description` field to be a string, found: " . gettype($item['description']) . "\n");
|
||||
++$error_count;
|
||||
}
|
||||
// `web` is an optional string[]
|
||||
if (isset($item['web'])) {
|
||||
if (gettype($item['web']) != 'array') {
|
||||
fprintf($lint_writer, "{$item['id']}: Expected `web` field to be an array, found: " . gettype($item['web']) . "\n");
|
||||
++$error_count;
|
||||
} else {
|
||||
foreach ($item['web'] as $site) {
|
||||
if (gettype($site) != 'string') {
|
||||
fprintf($lint_writer, "{$item['id']}: Expected `web` items to be a string, found: " . gettype($site) . "\n");
|
||||
++$error_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// `removal` is a string
|
||||
if (gettype($item['removal']) != 'string') {
|
||||
fprintf($lint_writer, "{$item['id']}: Expected `removal` field to be a string, found: " . gettype($item['removal']) . "\n");
|
||||
++$error_count;
|
||||
} else if (!in_array($item['removal'], SUPPORTED_REMOVAL_TYPES)) {
|
||||
fprintf($lint_writer, "{$item['id']}: Invalid `removal` type: {$item['removal']}\n");
|
||||
++$error_count;
|
||||
}
|
||||
// `warning` is an optional string
|
||||
if (isset($item['warning']) && gettype($item['warning']) != 'string') {
|
||||
fprintf($lint_writer, "{$item['id']}: Expected `warning` field to be a string, found: " . gettype($item['warning']) . "\n");
|
||||
++$error_count;
|
||||
}
|
||||
// `warning` is an optional string
|
||||
if (isset($item['suggestions'])) {
|
||||
if (gettype($item['suggestions']) != 'string') {
|
||||
fprintf($lint_writer, "{$item['id']}: Expected `suggestions` field to be a string, found: " . gettype($item['suggestions']) . "\n");
|
||||
++$error_count;
|
||||
} else {
|
||||
$suggestion_file = SUGGESTIONS_DIR . '/' . $item['suggestions'] . '.json';
|
||||
if (!file_exists($suggestion_file)) {
|
||||
fprintf($lint_writer, "{$item['id']}: Suggestion ID ({$item['suggestions']}) does not exist.\n");
|
||||
++$error_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $error_count;
|
||||
}
|
||||
|
||||
function validate_suggestion_item(array $item): int {
|
||||
global $lint_writer;
|
||||
$error_count = 0;
|
||||
// `id` is a string
|
||||
if (gettype($item['id']) != 'string') {
|
||||
fprintf($lint_writer, "Expected `id` field to be a string, found: " . gettype($item['id']) . "\n");
|
||||
++$error_count;
|
||||
}
|
||||
// `label` is a string
|
||||
if (gettype($item['label']) != 'string') {
|
||||
fprintf($lint_writer, "{$item['id']}: Expected `label` field to be a string, found: " . gettype($item['label']) . "\n");
|
||||
++$error_count;
|
||||
}
|
||||
// `reason` is an optional string
|
||||
if (isset($item['reason']) && gettype($item['reason']) != 'string') {
|
||||
fprintf($lint_writer, "{$item['id']}: Expected `reason` field to be a string, found: " . gettype($item['reason']) . "\n");
|
||||
++$error_count;
|
||||
}
|
||||
// `source` is an optional string
|
||||
if (isset($item['source'])) {
|
||||
if (gettype($item['source']) != 'string') {
|
||||
fprintf($lint_writer, "{$item['id']}: Expected `source` field to be a string, found: " . gettype($item['source']) . "\n");
|
||||
++$error_count;
|
||||
} else if (!preg_match("/^[fgas]+$/", $item['source'])) {
|
||||
fprintf($lint_writer, "{$item['id']}: Expected `source` field to contain one or more from `fgas`, found: {$item['source']}\n");
|
||||
++$error_count;
|
||||
}
|
||||
}
|
||||
// `repo` is a string
|
||||
if (gettype($item['repo']) != 'string') {
|
||||
fprintf($lint_writer, "{$item['id']}: Expected `repo` field to be a string, found: " . gettype($item['repo']) . "\n");
|
||||
++$error_count;
|
||||
}
|
||||
return $error_count;
|
||||
}
|
13
scripts/test.php
Normal file
13
scripts/test.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
$json_files = array_filter(scandir(__DIR__), function ($item) {
|
||||
return str_ends_with($item, ".json");
|
||||
});
|
||||
|
||||
foreach ($json_files as $json_file) {
|
||||
$list = json_decode(file_get_contents(__DIR__ . 'test.php/' . $json_file), true);
|
||||
usort($list, function ($o1, $o2) {
|
||||
return $o1['id'] <=> $o2['id'];
|
||||
});
|
||||
file_put_contents(__DIR__ . 'test.php/' . $json_file, json_encode($list, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
|
||||
}
|
118
scripts/update_uad.php
Normal file
118
scripts/update_uad.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
/* SPDX-License-Identifier: AGPL-3.0-or-later */
|
||||
|
||||
const LAST_COMMIT = "11f27c671cba278d71296cdef4c5a5dba06add5e";
|
||||
const THIS_COMMIT = "11f27c671cba278d71296cdef4c5a5dba06add5e";
|
||||
|
||||
const COLOR_RED = 31;
|
||||
const COLOR_GREEN = 32;
|
||||
|
||||
function get_link(string $commit_hash): string {
|
||||
return "https://raw.githubusercontent.com/0x192/universal-android-debloater/$commit_hash/resources/assets/uad_lists.json";
|
||||
}
|
||||
|
||||
$old_list_link = get_link(LAST_COMMIT);
|
||||
$new_list_link = get_link(THIS_COMMIT);
|
||||
|
||||
if ($old_list_link == $new_list_link) {
|
||||
echo "Already up-to-date.\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$old_list = json_decode(file_get_contents($old_list_link), true);
|
||||
$new_list = json_decode(file_get_contents($new_list_link), true);
|
||||
|
||||
// Iterate over the new list to find changes w.r.t old list. Delete the matched item from the old list
|
||||
foreach ($new_list as $item) {
|
||||
if ($item['removal'] == 'Unsafe') {
|
||||
// Exclude Unsafe items
|
||||
continue;
|
||||
}
|
||||
$old_item = find_in_old_list($item['id']);
|
||||
if ($item != $old_item) {
|
||||
// Two arrays aren't the same, check one by one and print values
|
||||
print(" {\n");
|
||||
foreach ($item as $key => $value) {
|
||||
if ($value != $old_item[$key]) {
|
||||
// These values aren't the same
|
||||
// Print diff
|
||||
print_diff($key, $old_item[$key], COLOR_RED);
|
||||
print_diff($key, $value, COLOR_GREEN);
|
||||
} else {
|
||||
// Values are the same, print as is
|
||||
print_diff($key, $value, null);
|
||||
}
|
||||
}
|
||||
print(" }\n");
|
||||
}
|
||||
}
|
||||
|
||||
// The remaining items in the old list are removed
|
||||
foreach ($old_list as $item) {
|
||||
if ($item['removal'] == 'Unsafe') {
|
||||
// Exclude Unsafe items
|
||||
continue;
|
||||
}
|
||||
// List this item as removed item.
|
||||
print("\e[31m-{\e[0m\n");
|
||||
foreach ($item as $key => $value) {
|
||||
print_diff($key, $value, null);
|
||||
}
|
||||
print("\e[31m-}\e[0m\n");
|
||||
}
|
||||
|
||||
exit(0);
|
||||
|
||||
function print_diff(string $key, string|array|null $value, ?int $color): void {
|
||||
if ($color == COLOR_RED) {
|
||||
$symbol = '-';
|
||||
$color_begin = "\e[31m";
|
||||
$color_end = "\e[0m";
|
||||
} else if ($color == COLOR_GREEN) {
|
||||
$symbol = '+';
|
||||
$color_begin = "\e[32m";
|
||||
$color_end = "\e[0m";
|
||||
} else {
|
||||
$symbol = ' ';
|
||||
$color_begin = '';
|
||||
$color_end = '';
|
||||
}
|
||||
if ($value == null) {
|
||||
printf("$symbol$color_begin $key: null,$color_end");
|
||||
} else if (is_string($value)) {
|
||||
printf("$symbol$color_begin $key: $value,$color_end");
|
||||
} else if (is_array($value)) {
|
||||
printf("$symbol$color_begin $key: [$color_end");
|
||||
foreach ($value as $item) {
|
||||
printf("$symbol$color_begin $item,$color_end");
|
||||
}
|
||||
printf("$symbol$color_begin ],$color_end");
|
||||
}
|
||||
}
|
||||
|
||||
function find_in_old_list(string $id): ?array {
|
||||
global $old_list;
|
||||
$c = count($old_list);
|
||||
for ($i = 0; $i < $c; ++$i) {
|
||||
$item = $old_list[$i];
|
||||
if ($item['id'] == $id) {
|
||||
array_splice($old_list, $i, 1);
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function get_removal(string $uad_removal): string {
|
||||
switch ($uad_removal) {
|
||||
default:
|
||||
case "Recommended":
|
||||
return "delete";
|
||||
case "Advanced":
|
||||
return "replace";
|
||||
case "Expert":
|
||||
return "caution";
|
||||
case "Unsafe":
|
||||
return "unsafe";
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user