mirror of
				https://github.com/f-droid/fdroidserver.git
				synced 2025-11-04 06:30:27 +03:00 
			
		
		
		
	scanner: support libs.versions.toml
This commit is contained in:
		
							parent
							
								
									528760acc8
								
							
						
					
					
						commit
						eff0ef48f4
					
				
					 17 changed files with 723 additions and 35 deletions
				
			
		
							
								
								
									
										13
									
								
								MANIFEST.in
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								MANIFEST.in
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -741,6 +741,11 @@ include tests/signindex/guardianproject-v1.jar
 | 
			
		|||
include tests/signindex/testy.jar
 | 
			
		||||
include tests/signindex/unsigned.jar
 | 
			
		||||
include tests/source-files/at.bitfire.davdroid/build.gradle
 | 
			
		||||
include tests/source-files/catalog.test/app/build.gradle
 | 
			
		||||
include tests/source-files/catalog.test/build.gradle.kts
 | 
			
		||||
include tests/source-files/catalog.test/libs.versions.toml
 | 
			
		||||
include tests/source-files/catalog.test/gradle/libs.versions.toml
 | 
			
		||||
include tests/source-files/catalog.test/settings.gradle.kts
 | 
			
		||||
include tests/source-files/cn.wildfirechat.chat/avenginekit/build.gradle
 | 
			
		||||
include tests/source-files/cn.wildfirechat.chat/build.gradle
 | 
			
		||||
include tests/source-files/cn.wildfirechat.chat/chat/build.gradle
 | 
			
		||||
| 
						 | 
				
			
			@ -775,6 +780,11 @@ include tests/source-files/com.integreight.onesheeld/settings.gradle
 | 
			
		|||
include tests/source-files/com.jens.automation2/build.gradle
 | 
			
		||||
include tests/source-files/com.jens.automation2/app/build.gradle
 | 
			
		||||
include tests/source-files/com.kunzisoft.testcase/build.gradle
 | 
			
		||||
include tests/source-files/com.lolo.io.onelist/app/build.gradle.kts
 | 
			
		||||
include tests/source-files/com.lolo.io.onelist/build.gradle.kts
 | 
			
		||||
include tests/source-files/com.lolo.io.onelist/gradle/libs.versions.toml
 | 
			
		||||
include tests/source-files/com.lolo.io.onelist/gradle/wrapper/gradle-wrapper.properties
 | 
			
		||||
include tests/source-files/com.lolo.io.onelist/settings.gradle
 | 
			
		||||
include tests/source-files/com.nextcloud.client/build.gradle
 | 
			
		||||
include tests/source-files/com.nextcloud.client.dev/src/generic/fastlane/metadata/android/en-US/full_description.txt
 | 
			
		||||
include tests/source-files/com.nextcloud.client.dev/src/generic/fastlane/metadata/android/en-US/short_description.txt
 | 
			
		||||
| 
						 | 
				
			
			@ -817,6 +827,9 @@ include tests/source-files/org.mozilla.rocket/app/build.gradle
 | 
			
		|||
include tests/source-files/org.noise_planet.noisecapture/app/build.gradle
 | 
			
		||||
include tests/source-files/org.noise_planet.noisecapture/settings.gradle
 | 
			
		||||
include tests/source-files/org.noise_planet.noisecapture/sosfilter/build.gradle
 | 
			
		||||
include tests/source-files/org.piepmeyer.gauguin/build.gradle.kts
 | 
			
		||||
include tests/source-files/org.piepmeyer.gauguin/libs.versions.toml
 | 
			
		||||
include tests/source-files/org.piepmeyer.gauguin/settings.gradle.kts
 | 
			
		||||
include tests/source-files/org.tasks/app/build.gradle.kts
 | 
			
		||||
include tests/source-files/org.tasks/build.gradle
 | 
			
		||||
include tests/source-files/org.tasks/build.gradle.kts
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,11 @@ from enum import IntEnum
 | 
			
		|||
from pathlib import Path
 | 
			
		||||
from tempfile import TemporaryDirectory
 | 
			
		||||
 | 
			
		||||
if sys.version_info >= (3, 11):
 | 
			
		||||
    import tomllib
 | 
			
		||||
else:
 | 
			
		||||
    import tomli as tomllib
 | 
			
		||||
 | 
			
		||||
from . import _, common, metadata, scanner
 | 
			
		||||
from .exception import BuildException, ConfigurationException, VCSException
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -58,13 +63,177 @@ DEPFILE = {
 | 
			
		|||
 | 
			
		||||
SCANNER_CACHE_VERSION = 1
 | 
			
		||||
 | 
			
		||||
DEFAULT_CATALOG_PREFIX_REGEX = re.compile(
 | 
			
		||||
    r'''defaultLibrariesExtensionName\s*=\s*['"](\w+)['"]'''
 | 
			
		||||
)
 | 
			
		||||
GRADLE_KTS_CATALOG_FILE_REGEX = re.compile(
 | 
			
		||||
    r'''create\("(\w+)"\)\s*\{[^}]*from\(files\(['"]([^"]+)['"]\)\)'''
 | 
			
		||||
)
 | 
			
		||||
GRADLE_CATALOG_FILE_REGEX = re.compile(
 | 
			
		||||
    r'''(\w+)\s*\{[^}]*from\(files\(['"]([^"]+)['"]\)\)'''
 | 
			
		||||
)
 | 
			
		||||
VERSION_CATALOG_REGEX = re.compile(
 | 
			
		||||
    r'dependencyResolutionManagement\s*\{[^}]*versionCatalogs\s*\{'
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ExitCode(IntEnum):
 | 
			
		||||
    NONFREE_CODE = 1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GradleVersionCatalog:
 | 
			
		||||
    """Parse catalog from libs.versions.toml.
 | 
			
		||||
 | 
			
		||||
    https://docs.gradle.org/current/userguide/platforms.html
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, catalog):
 | 
			
		||||
        self.version = {
 | 
			
		||||
            alias: self.get_version(version)
 | 
			
		||||
            for alias, version in catalog.get("versions", {}).items()
 | 
			
		||||
        }
 | 
			
		||||
        self.libraries = {
 | 
			
		||||
            self.alias_to_accessor(alias): self.library_to_coordinate(library)
 | 
			
		||||
            for alias, library in catalog.get("libraries", {}).items()
 | 
			
		||||
        }
 | 
			
		||||
        self.plugins = {
 | 
			
		||||
            self.alias_to_accessor(alias): self.plugin_to_coordinate(plugin)
 | 
			
		||||
            for alias, plugin in catalog.get("plugins", {}).items()
 | 
			
		||||
        }
 | 
			
		||||
        self.bundles = {
 | 
			
		||||
            self.alias_to_accessor(alias): self.bundle_to_coordinates(bundle)
 | 
			
		||||
            for alias, bundle in catalog.get("bundles", {}).items()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def alias_to_accessor(alias: str) -> str:
 | 
			
		||||
        """Covert alias to accessor.
 | 
			
		||||
 | 
			
		||||
        https://docs.gradle.org/current/userguide/platforms.html#sub:mapping-aliases-to-accessors
 | 
			
		||||
        Alias is used to define a lib in catalog. Accessor is used to access it.
 | 
			
		||||
        """
 | 
			
		||||
        return alias.replace("-", ".").replace("_", ".")
 | 
			
		||||
 | 
			
		||||
    def get_version(self, version: dict) -> str:
 | 
			
		||||
        if isinstance(version, str):
 | 
			
		||||
            return version
 | 
			
		||||
        ref = version.get("ref")
 | 
			
		||||
        if ref:
 | 
			
		||||
            return self.version.get(ref, "")
 | 
			
		||||
        return (
 | 
			
		||||
            version.get("prefer", "")
 | 
			
		||||
            or version.get("require", "")
 | 
			
		||||
            or version.get("strictly", "")
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def library_to_coordinate(self, library: dict) -> str:
 | 
			
		||||
        """Generate the Gradle dependency coordinate from catalog."""
 | 
			
		||||
        module = library.get("module")
 | 
			
		||||
        if not module:
 | 
			
		||||
            group = library.get("group")
 | 
			
		||||
            name = library.get("name")
 | 
			
		||||
            if group and name:
 | 
			
		||||
                module = f"{group}:{name}"
 | 
			
		||||
            else:
 | 
			
		||||
                return ""
 | 
			
		||||
 | 
			
		||||
        version = library.get("version")
 | 
			
		||||
        if version:
 | 
			
		||||
            return f"{module}:{self.get_version(version)}"
 | 
			
		||||
        else:
 | 
			
		||||
            return module
 | 
			
		||||
 | 
			
		||||
    def plugin_to_coordinate(self, plugin: dict) -> str:
 | 
			
		||||
        """Generate the Gradle plugin coordinate from catalog."""
 | 
			
		||||
        id = plugin.get("id")
 | 
			
		||||
        if not id:
 | 
			
		||||
            return ""
 | 
			
		||||
 | 
			
		||||
        version = plugin.get("version")
 | 
			
		||||
        if version:
 | 
			
		||||
            return f"{id}:{self.get_version(version)}"
 | 
			
		||||
        else:
 | 
			
		||||
            return id
 | 
			
		||||
 | 
			
		||||
    def bundle_to_coordinates(self, bundle) -> list[str]:
 | 
			
		||||
        """Generate the Gradle dependency bundle coordinate from catalog."""
 | 
			
		||||
        coordinates = []
 | 
			
		||||
        for alias in bundle:
 | 
			
		||||
            library = self.libraries.get(self.alias_to_accessor(alias))
 | 
			
		||||
            if library:
 | 
			
		||||
                coordinates.append(library)
 | 
			
		||||
        return coordinates
 | 
			
		||||
 | 
			
		||||
    def get_coordinate(self, accessor: str) -> list[str]:
 | 
			
		||||
        """Get the Gradle coordinate from the catalog with an accessor."""
 | 
			
		||||
        if accessor.startswith("plugins."):
 | 
			
		||||
            return [self.plugins.get(accessor[8:], "")]
 | 
			
		||||
        if accessor.startswith("bundles."):
 | 
			
		||||
            return self.bundles.get(accessor[8:], [])
 | 
			
		||||
        return [self.libraries.get(accessor, "")]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_catalogs(root: str) -> dict[str, GradleVersionCatalog]:
 | 
			
		||||
    """Get all Gradle dependency catalogs from settings.gradle[.kts].
 | 
			
		||||
 | 
			
		||||
    Returns a dict with the extension and the corresponding catalog.
 | 
			
		||||
    The extension is used as the prefix of the accessor to access libs in the catalog.
 | 
			
		||||
    """
 | 
			
		||||
    root = Path(root)
 | 
			
		||||
    catalogs = {}
 | 
			
		||||
    default_prefix = "libs"
 | 
			
		||||
    catalog_files_m = []
 | 
			
		||||
 | 
			
		||||
    def find_block_end(s, start):
 | 
			
		||||
        pat = re.compile("[{}]")
 | 
			
		||||
        depth = 1
 | 
			
		||||
        for m in pat.finditer(s, pos=start):
 | 
			
		||||
            if m.group() == "{":
 | 
			
		||||
                depth += 1
 | 
			
		||||
            else:
 | 
			
		||||
                depth -= 1
 | 
			
		||||
            if depth == 0:
 | 
			
		||||
                return m.start()
 | 
			
		||||
        else:
 | 
			
		||||
            return -1
 | 
			
		||||
 | 
			
		||||
    groovy_file = root / "settings.gradle"
 | 
			
		||||
    kotlin_file = root / "settings.gradle.kts"
 | 
			
		||||
    if groovy_file.is_file():
 | 
			
		||||
        s = groovy_file.read_text(encoding="utf-8")
 | 
			
		||||
        version_catalogs_m = VERSION_CATALOG_REGEX.search(s)
 | 
			
		||||
        if version_catalogs_m:
 | 
			
		||||
            start = version_catalogs_m.end()
 | 
			
		||||
            end = find_block_end(s, start)
 | 
			
		||||
            catalog_files_m = GRADLE_CATALOG_FILE_REGEX.finditer(s, start, end)
 | 
			
		||||
    elif kotlin_file.is_file():
 | 
			
		||||
        s = kotlin_file.read_text(encoding="utf-8")
 | 
			
		||||
        version_catalogs_m = VERSION_CATALOG_REGEX.search(s)
 | 
			
		||||
        if version_catalogs_m:
 | 
			
		||||
            start = version_catalogs_m.end()
 | 
			
		||||
            end = find_block_end(s, start)
 | 
			
		||||
            catalog_files_m = GRADLE_KTS_CATALOG_FILE_REGEX.finditer(s, start, end)
 | 
			
		||||
    else:
 | 
			
		||||
        return {}
 | 
			
		||||
 | 
			
		||||
    m_default = DEFAULT_CATALOG_PREFIX_REGEX.search(s)
 | 
			
		||||
    if m_default:
 | 
			
		||||
        default_prefix = m_default.group(1)
 | 
			
		||||
    default_catalog_file = Path(root) / "gradle/libs.versions.toml"
 | 
			
		||||
    if default_catalog_file.is_file():
 | 
			
		||||
        with default_catalog_file.open("rb") as f:
 | 
			
		||||
            catalogs[default_prefix] = GradleVersionCatalog(tomllib.load(f))
 | 
			
		||||
    for m in catalog_files_m:
 | 
			
		||||
        catalog_file = Path(root) / m.group(2).replace("$rootDir/", "")
 | 
			
		||||
        if catalog_file.is_file():
 | 
			
		||||
            with catalog_file.open("rb") as f:
 | 
			
		||||
                catalogs[m.group(1)] = GradleVersionCatalog(tomllib.load(f))
 | 
			
		||||
    return catalogs
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_gradle_compile_commands(build):
 | 
			
		||||
    compileCommands = [
 | 
			
		||||
        'alias',
 | 
			
		||||
        'api',
 | 
			
		||||
        'apk',
 | 
			
		||||
        'classpath',
 | 
			
		||||
| 
						 | 
				
			
			@ -80,15 +249,25 @@ def get_gradle_compile_commands(build):
 | 
			
		|||
    if build.gradle and build.gradle != ['yes']:
 | 
			
		||||
        flavors += build.gradle
 | 
			
		||||
 | 
			
		||||
    commands = [
 | 
			
		||||
        ''.join(c) for c in itertools.product(flavors, buildTypes, compileCommands)
 | 
			
		||||
    return [''.join(c) for c in itertools.product(flavors, buildTypes, compileCommands)]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_gradle_compile_commands_without_catalog(build):
 | 
			
		||||
    return [
 | 
			
		||||
        re.compile(rf'''\s*{c}.*\s*\(?['"].*['"]''', re.IGNORECASE)
 | 
			
		||||
        for c in get_gradle_compile_commands(build)
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_gradle_compile_commands_with_catalog(build, prefix):
 | 
			
		||||
    return [
 | 
			
		||||
        re.compile(rf'\s*{c}.*\s*\(?{prefix}\.([a-z0-9.]+)', re.IGNORECASE)
 | 
			
		||||
        for c in get_gradle_compile_commands(build)
 | 
			
		||||
    ]
 | 
			
		||||
    return [re.compile(r'\s*' + c, re.IGNORECASE) for c in commands]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_embedded_classes(apkfile, depth=0):
 | 
			
		||||
    """
 | 
			
		||||
    Get the list of Java classes embedded into all DEX files.
 | 
			
		||||
    """Get the list of Java classes embedded into all DEX files.
 | 
			
		||||
 | 
			
		||||
    :return: set of Java classes names as string
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			@ -183,8 +362,7 @@ class SignatureDataController:
 | 
			
		|||
            raise SignatureDataVersionMismatchException()
 | 
			
		||||
 | 
			
		||||
    def check_last_updated(self):
 | 
			
		||||
        """
 | 
			
		||||
        Check if the last_updated value is ok and raise an exception if expired or inaccessible.
 | 
			
		||||
        """Check if the last_updated value is ok and raise an exception if expired or inaccessible.
 | 
			
		||||
 | 
			
		||||
        :raises SignatureDataMalformedException: when timestamp value is
 | 
			
		||||
                                                 inaccessible or not parse-able
 | 
			
		||||
| 
						 | 
				
			
			@ -259,8 +437,7 @@ class SignatureDataController:
 | 
			
		|||
        logging.debug("write '{}' to cache".format(self.filename))
 | 
			
		||||
 | 
			
		||||
    def verify_data(self):
 | 
			
		||||
        """
 | 
			
		||||
        Clean and validate `self.data`.
 | 
			
		||||
        """Clean and validate `self.data`.
 | 
			
		||||
 | 
			
		||||
        Right now this function does just a basic key sanitation.
 | 
			
		||||
        """
 | 
			
		||||
| 
						 | 
				
			
			@ -451,8 +628,7 @@ _SCANNER_TOOL = None
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
def _get_tool():
 | 
			
		||||
    """
 | 
			
		||||
    Lazy loading function for getting a ScannerTool instance.
 | 
			
		||||
    """Lazy loading function for getting a ScannerTool instance.
 | 
			
		||||
 | 
			
		||||
    ScannerTool initialization need to access `common.config` values. Those are only available after initialization through `common.read_config()`. So this factory assumes config was called at an erlier point in time.
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			@ -496,6 +672,7 @@ def scan_source(build_dir, build=metadata.Build(), json_per_build=None):
 | 
			
		|||
    Returns
 | 
			
		||||
    -------
 | 
			
		||||
    the number of fatal problems encountered.
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    count = 0
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -571,6 +748,7 @@ def scan_source(build_dir, build=metadata.Build(), json_per_build=None):
 | 
			
		|||
        Returns
 | 
			
		||||
        -------
 | 
			
		||||
        0 as we explicitly ignore the file, so don't count an error
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        msg = 'Ignoring %s at %s' % (what, path_in_build_dir)
 | 
			
		||||
        logging.info(msg)
 | 
			
		||||
| 
						 | 
				
			
			@ -593,6 +771,7 @@ def scan_source(build_dir, build=metadata.Build(), json_per_build=None):
 | 
			
		|||
        Returns
 | 
			
		||||
        -------
 | 
			
		||||
        0 as we deleted the offending file
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        msg = 'Removing %s at %s' % (what, path_in_build_dir)
 | 
			
		||||
        logging.info(msg)
 | 
			
		||||
| 
						 | 
				
			
			@ -620,6 +799,7 @@ def scan_source(build_dir, build=metadata.Build(), json_per_build=None):
 | 
			
		|||
        Returns
 | 
			
		||||
        -------
 | 
			
		||||
        0, as warnings don't count as errors
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        if toignore(path_in_build_dir):
 | 
			
		||||
            return 0
 | 
			
		||||
| 
						 | 
				
			
			@ -645,6 +825,7 @@ def scan_source(build_dir, build=metadata.Build(), json_per_build=None):
 | 
			
		|||
        Returns
 | 
			
		||||
        -------
 | 
			
		||||
        0 if the problem was ignored/deleted/is only a warning, 1 otherwise
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        options = common.get_options()
 | 
			
		||||
        if toignore(path_in_build_dir):
 | 
			
		||||
| 
						 | 
				
			
			@ -691,11 +872,21 @@ def scan_source(build_dir, build=metadata.Build(), json_per_build=None):
 | 
			
		|||
                return True
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    gradle_compile_commands = get_gradle_compile_commands(build)
 | 
			
		||||
    def is_used_by_gradle_without_catalog(line):
 | 
			
		||||
        return any(
 | 
			
		||||
            command.match(line)
 | 
			
		||||
            for command in get_gradle_compile_commands_without_catalog(build)
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def is_used_by_gradle(line):
 | 
			
		||||
        return any(command.match(line) for command in gradle_compile_commands)
 | 
			
		||||
    def is_used_by_gradle_with_catalog(line, prefix):
 | 
			
		||||
        for m in (
 | 
			
		||||
            command.match(line)
 | 
			
		||||
            for command in get_gradle_compile_commands_with_catalog(build, prefix)
 | 
			
		||||
        ):
 | 
			
		||||
            if m:
 | 
			
		||||
                return m
 | 
			
		||||
 | 
			
		||||
    catalogs = {}
 | 
			
		||||
    # Iterate through all files in the source code
 | 
			
		||||
    for root, dirs, files in os.walk(build_dir, topdown=True):
 | 
			
		||||
        # It's topdown, so checking the basename is enough
 | 
			
		||||
| 
						 | 
				
			
			@ -703,6 +894,9 @@ def scan_source(build_dir, build=metadata.Build(), json_per_build=None):
 | 
			
		|||
            if ignoredir in dirs:
 | 
			
		||||
                dirs.remove(ignoredir)
 | 
			
		||||
 | 
			
		||||
        if "settings.gradle" in files or "settings.gradle.kts" in files:
 | 
			
		||||
            catalogs = get_catalogs(root)
 | 
			
		||||
 | 
			
		||||
        for curfile in files:
 | 
			
		||||
            if curfile in ['.DS_Store']:
 | 
			
		||||
                continue
 | 
			
		||||
| 
						 | 
				
			
			@ -789,14 +983,28 @@ def scan_source(build_dir, build=metadata.Build(), json_per_build=None):
 | 
			
		|||
                with open(filepath, 'r', errors='replace') as f:
 | 
			
		||||
                    lines = f.readlines()
 | 
			
		||||
                for i, line in enumerate(lines):
 | 
			
		||||
                    if is_used_by_gradle(line):
 | 
			
		||||
                    if is_used_by_gradle_without_catalog(line):
 | 
			
		||||
                        for name in suspects_found(line):
 | 
			
		||||
                            count += handleproblem(
 | 
			
		||||
                                "usual suspect '%s'" % (name),
 | 
			
		||||
                                f"usual suspect '{name}'",
 | 
			
		||||
                                path_in_build_dir,
 | 
			
		||||
                                filepath,
 | 
			
		||||
                                json_per_build,
 | 
			
		||||
                            )
 | 
			
		||||
                    for prefix, catalog in catalogs.items():
 | 
			
		||||
                        m = is_used_by_gradle_with_catalog(line, prefix)
 | 
			
		||||
                        if not m:
 | 
			
		||||
                            continue
 | 
			
		||||
                        accessor = m[1]
 | 
			
		||||
                        coordinates = catalog.get_coordinate(accessor)
 | 
			
		||||
                        for coordinate in coordinates:
 | 
			
		||||
                            for name in suspects_found(coordinate):
 | 
			
		||||
                                count += handleproblem(
 | 
			
		||||
                                    f"usual suspect '{prefix}.{accessor}: {name}'",
 | 
			
		||||
                                    path_in_build_dir,
 | 
			
		||||
                                    filepath,
 | 
			
		||||
                                    json_per_build,
 | 
			
		||||
                                )
 | 
			
		||||
                noncomment_lines = [
 | 
			
		||||
                    line for line in lines if not common.gradle_comment.match(line)
 | 
			
		||||
                ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								setup.py
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								setup.py
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -4,8 +4,7 @@ import re
 | 
			
		|||
import subprocess
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
from setuptools import Command
 | 
			
		||||
from setuptools import setup
 | 
			
		||||
from setuptools import Command, setup
 | 
			
		||||
from setuptools.command.install import install
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -108,6 +107,7 @@ setup(
 | 
			
		|||
        'requests >= 2.5.2, != 2.11.0, != 2.12.2, != 2.18.0',
 | 
			
		||||
        'sdkmanager >= 0.6.4',
 | 
			
		||||
        'yamllint',
 | 
			
		||||
        'tomli >= 1.1.0; python_version < "3.11"',
 | 
			
		||||
    ],
 | 
			
		||||
    # Some requires are only needed for very limited cases:
 | 
			
		||||
    # * biplist is only used for parsing Apple .ipa files
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,10 @@ from dataclasses import asdict
 | 
			
		|||
from datetime import datetime, timedelta
 | 
			
		||||
from unittest import mock
 | 
			
		||||
 | 
			
		||||
if sys.version_info >= (3, 11):
 | 
			
		||||
    import tomllib
 | 
			
		||||
else:
 | 
			
		||||
    import tomli as tomllib
 | 
			
		||||
import yaml
 | 
			
		||||
 | 
			
		||||
localmodule = os.path.realpath(
 | 
			
		||||
| 
						 | 
				
			
			@ -70,6 +74,8 @@ class ScannerTest(unittest.TestCase):
 | 
			
		|||
            'realm': 1,
 | 
			
		||||
            'se.manyver': 3,
 | 
			
		||||
            'lockfile.test': 1,
 | 
			
		||||
            'com.lolo.io.onelist': 6,
 | 
			
		||||
            'catalog.test': 10,
 | 
			
		||||
        }
 | 
			
		||||
        for d in glob.glob(os.path.join(source_files, '*')):
 | 
			
		||||
            build = fdroidserver.metadata.Build()
 | 
			
		||||
| 
						 | 
				
			
			@ -79,26 +85,28 @@ class ScannerTest(unittest.TestCase):
 | 
			
		|||
                should, fatal_problems, "%s should have %d errors!" % (d, should)
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
    def test_get_gradle_compile_commands(self):
 | 
			
		||||
    def test_get_gradle_compile_commands_without_catalog(self):
 | 
			
		||||
        test_files = [
 | 
			
		||||
            ('source-files/fdroid/fdroidclient/build.gradle', 'yes', 18),
 | 
			
		||||
            ('source-files/com.nextcloud.client/build.gradle', 'generic', 28),
 | 
			
		||||
            ('source-files/com.kunzisoft.testcase/build.gradle', 'libre', 4),
 | 
			
		||||
            ('source-files/cn.wildfirechat.chat/chat/build.gradle', 'yes', 33),
 | 
			
		||||
            ('source-files/org.tasks/app/build.gradle.kts', 'generic', 43),
 | 
			
		||||
            ('source-files/at.bitfire.davdroid/build.gradle', 'standard', 16),
 | 
			
		||||
            ('source-files/se.manyver/android/app/build.gradle', 'indie', 29),
 | 
			
		||||
            ('source-files/osmandapp/osmand/build.gradle', 'free', 5),
 | 
			
		||||
            ('source-files/eu.siacs.conversations/build.gradle', 'free', 24),
 | 
			
		||||
            ('source-files/org.mozilla.rocket/app/build.gradle', 'focus', 42),
 | 
			
		||||
            ('source-files/com.jens.automation2/app/build.gradle', 'fdroidFlavor', 9),
 | 
			
		||||
            ('source-files/fdroid/fdroidclient/build.gradle', 'yes', 15),
 | 
			
		||||
            ('source-files/com.nextcloud.client/build.gradle', 'generic', 24),
 | 
			
		||||
            ('source-files/com.kunzisoft.testcase/build.gradle', 'libre', 3),
 | 
			
		||||
            ('source-files/cn.wildfirechat.chat/chat/build.gradle', 'yes', 30),
 | 
			
		||||
            ('source-files/org.tasks/app/build.gradle.kts', 'generic', 41),
 | 
			
		||||
            ('source-files/at.bitfire.davdroid/build.gradle', 'standard', 15),
 | 
			
		||||
            ('source-files/se.manyver/android/app/build.gradle', 'indie', 26),
 | 
			
		||||
            ('source-files/osmandapp/osmand/build.gradle', 'free', 2),
 | 
			
		||||
            ('source-files/eu.siacs.conversations/build.gradle', 'free', 21),
 | 
			
		||||
            ('source-files/org.mozilla.rocket/app/build.gradle', 'focus', 40),
 | 
			
		||||
            ('source-files/com.jens.automation2/app/build.gradle', 'fdroidFlavor', 5),
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
        for f, flavor, count in test_files:
 | 
			
		||||
            i = 0
 | 
			
		||||
            build = fdroidserver.metadata.Build()
 | 
			
		||||
            build.gradle = [flavor]
 | 
			
		||||
            regexs = fdroidserver.scanner.get_gradle_compile_commands(build)
 | 
			
		||||
            regexs = fdroidserver.scanner.get_gradle_compile_commands_without_catalog(
 | 
			
		||||
                build
 | 
			
		||||
            )
 | 
			
		||||
            with open(f, encoding='utf-8') as fp:
 | 
			
		||||
                for line in fp.readlines():
 | 
			
		||||
                    for regex in regexs:
 | 
			
		||||
| 
						 | 
				
			
			@ -107,6 +115,56 @@ class ScannerTest(unittest.TestCase):
 | 
			
		|||
                            i += 1
 | 
			
		||||
            self.assertEqual(count, i)
 | 
			
		||||
 | 
			
		||||
    def test_get_gradle_compile_commands_with_catalog(self):
 | 
			
		||||
        test_files = [
 | 
			
		||||
            ('source-files/com.lolo.io.onelist/build.gradle.kts', 'yes', 5),
 | 
			
		||||
            ('source-files/com.lolo.io.onelist/app/build.gradle.kts', 'yes', 26),
 | 
			
		||||
            ('source-files/catalog.test/build.gradle.kts', 'yes', 3),
 | 
			
		||||
            ('source-files/catalog.test/app/build.gradle', 'yes', 2),
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
        for f, flavor, count in test_files:
 | 
			
		||||
            i = 0
 | 
			
		||||
            build = fdroidserver.metadata.Build()
 | 
			
		||||
            build.gradle = [flavor]
 | 
			
		||||
            regexs = fdroidserver.scanner.get_gradle_compile_commands_with_catalog(
 | 
			
		||||
                build, "libs"
 | 
			
		||||
            )
 | 
			
		||||
            with open(f, encoding='utf-8') as fp:
 | 
			
		||||
                for line in fp.readlines():
 | 
			
		||||
                    for regex in regexs:
 | 
			
		||||
                        m = regex.match(line)
 | 
			
		||||
                        if m:
 | 
			
		||||
                            i += 1
 | 
			
		||||
            self.assertEqual(count, i)
 | 
			
		||||
 | 
			
		||||
    def test_catalog(self):
 | 
			
		||||
        accessor_coordinate_pairs = {
 | 
			
		||||
            'firebase.crash': ['com.google.firebase:firebase-crash:1.1.1'],
 | 
			
		||||
            'firebase.core': ['com.google.firebase:firebase-core:2.2.2'],
 | 
			
		||||
            'play.service.ads': ['com.google.android.gms:play-services-ads:1.2.1'],
 | 
			
		||||
            'plugins.google.services': ['com.google.gms.google-services:1.2.1'],
 | 
			
		||||
            'plugins.firebase.crashlytics': ['com.google.firebase.crashlytics:1.1.1'],
 | 
			
		||||
            'bundles.firebase': [
 | 
			
		||||
                'com.google.firebase:firebase-crash:1.1.1',
 | 
			
		||||
                'com.google.firebase:firebase-core:2.2.2',
 | 
			
		||||
            ],
 | 
			
		||||
        }
 | 
			
		||||
        with open('source-files/catalog.test/gradle/libs.versions.toml', 'rb') as f:
 | 
			
		||||
            catalog = fdroidserver.scanner.GradleVersionCatalog(tomllib.load(f))
 | 
			
		||||
        for accessor, coordinate in accessor_coordinate_pairs.items():
 | 
			
		||||
            self.assertEqual(catalog.get_coordinate(accessor), coordinate)
 | 
			
		||||
 | 
			
		||||
    def test_get_catalogs(self):
 | 
			
		||||
        test_files = [
 | 
			
		||||
            ('source-files/com.lolo.io.onelist/', 1),
 | 
			
		||||
            ('source-files/catalog.test/', 3),
 | 
			
		||||
            ('source-files/org.piepmeyer.gauguin/', 1),
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
        for root, count in test_files:
 | 
			
		||||
            self.assertEqual(count, len(fdroidserver.scanner.get_catalogs(root)))
 | 
			
		||||
 | 
			
		||||
    def test_scan_source_files_sneaky_maven(self):
 | 
			
		||||
        """Check for sneaking in banned maven repos"""
 | 
			
		||||
        os.chdir(self.testdir)
 | 
			
		||||
| 
						 | 
				
			
			@ -780,8 +838,7 @@ class Test_main(unittest.TestCase):
 | 
			
		|||
        self.scan_binary_func = mock.Mock(return_value=0)
 | 
			
		||||
 | 
			
		||||
    def test_parsing_appid(self):
 | 
			
		||||
        """
 | 
			
		||||
        This test verifies that app id get parsed correctly
 | 
			
		||||
        """This test verifies that app id get parsed correctly
 | 
			
		||||
        (doesn't test how they get processed)
 | 
			
		||||
        """
 | 
			
		||||
        self.args = ["com.example.app"]
 | 
			
		||||
| 
						 | 
				
			
			@ -802,8 +859,7 @@ class Test_main(unittest.TestCase):
 | 
			
		|||
            self.scan_binary_func.assert_not_called()
 | 
			
		||||
 | 
			
		||||
    def test_parsing_apkpath(self):
 | 
			
		||||
        """
 | 
			
		||||
        This test verifies that apk paths get parsed correctly
 | 
			
		||||
        """This test verifies that apk paths get parsed correctly
 | 
			
		||||
        (doesn't test how they get processed)
 | 
			
		||||
        """
 | 
			
		||||
        self.args = ["local.application.apk"]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								tests/source-files/catalog.test/app/build.gradle
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								tests/source-files/catalog.test/app/build.gradle
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
implementation libs.bundles.firebase
 | 
			
		||||
implementation libs.play.service.ads
 | 
			
		||||
							
								
								
									
										5
									
								
								tests/source-files/catalog.test/build.gradle.kts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								tests/source-files/catalog.test/build.gradle.kts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
plugins {
 | 
			
		||||
    alias(libs.plugins.google.services)
 | 
			
		||||
    alias(libs.plugins.firebase.crashlytics)
 | 
			
		||||
    alias(projectLibs.plugins.firebase.crashlytics)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								tests/source-files/catalog.test/gradle/libs.versions.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								tests/source-files/catalog.test/gradle/libs.versions.toml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
[versions]
 | 
			
		||||
firebase = "1.1.1"
 | 
			
		||||
gms = "1.2.1"
 | 
			
		||||
 | 
			
		||||
[libraries]
 | 
			
		||||
firebase-crash = { module = "com.google.firebase:firebase-crash", version.ref = "firebase" }
 | 
			
		||||
firebase_core = { module = "com.google.firebase:firebase-core", version = "2.2.2" }
 | 
			
		||||
"play.service.ads" = { module = "com.google.android.gms:play-services-ads", version.ref = "gms"}
 | 
			
		||||
 | 
			
		||||
[plugins]
 | 
			
		||||
google-services = { id = "com.google.gms.google-services", version.ref = "gms" }
 | 
			
		||||
firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebase" }
 | 
			
		||||
 | 
			
		||||
[bundles]
 | 
			
		||||
firebase = ["firebase-crash", "firebase_core"]
 | 
			
		||||
							
								
								
									
										15
									
								
								tests/source-files/catalog.test/libs.versions.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								tests/source-files/catalog.test/libs.versions.toml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
[versions]
 | 
			
		||||
firebase = "1.1.1"
 | 
			
		||||
gms = "1.2.1"
 | 
			
		||||
 | 
			
		||||
[libraries]
 | 
			
		||||
firebase-crash = { module = "com.google.firebase:firebase-crash", version.ref = "firebase" }
 | 
			
		||||
firebase_core = { module = "com.google.firebase:firebase-core", version = "2.2.2" }
 | 
			
		||||
"play.service.ads" = { module = "com.google.android.gms:play-services-ads", version.ref = "gms"}
 | 
			
		||||
 | 
			
		||||
[plugins]
 | 
			
		||||
google-services = { id = "com.google.gms.google-services", version.ref = "gms" }
 | 
			
		||||
firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebase" }
 | 
			
		||||
 | 
			
		||||
[bundles]
 | 
			
		||||
firebase = ["firebase-crash", "firebase_core"]
 | 
			
		||||
							
								
								
									
										11
									
								
								tests/source-files/catalog.test/settings.gradle.kts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								tests/source-files/catalog.test/settings.gradle.kts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
dependencyResolutionManagement {
 | 
			
		||||
    defaultLibrariesExtensionName = "projectLibs"
 | 
			
		||||
    versionCatalogs {
 | 
			
		||||
        create("libs") {
 | 
			
		||||
            from(files("./libs.versions.toml"))
 | 
			
		||||
        }
 | 
			
		||||
        create("anotherLibs") {
 | 
			
		||||
            from(files("$rootDir/libs.versions.toml"))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										118
									
								
								tests/source-files/com.lolo.io.onelist/app/build.gradle.kts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								tests/source-files/com.lolo.io.onelist/app/build.gradle.kts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,118 @@
 | 
			
		|||
import java.io.FileInputStream
 | 
			
		||||
import java.util.Properties
 | 
			
		||||
 | 
			
		||||
plugins {
 | 
			
		||||
    alias(libs.plugins.android.application)
 | 
			
		||||
    alias(libs.plugins.kotlin.android)
 | 
			
		||||
    alias(libs.plugins.google.services)
 | 
			
		||||
    alias(libs.plugins.firebase.crashlytics)
 | 
			
		||||
    alias(libs.plugins.ksp)
 | 
			
		||||
}
 | 
			
		||||
android {
 | 
			
		||||
    namespace = "com.lolo.io.onelist"
 | 
			
		||||
 | 
			
		||||
    val versionPropsFile = file("../version.properties")
 | 
			
		||||
    var versionCodeCI: Int? = null
 | 
			
		||||
    if (versionPropsFile.canRead()) {
 | 
			
		||||
        val versionProps = Properties()
 | 
			
		||||
        versionProps.load(FileInputStream(versionPropsFile))
 | 
			
		||||
        val v = versionProps["VERSION_CODE"]
 | 
			
		||||
        versionCodeCI = (versionProps["VERSION_CODE"] as String).toInt()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    defaultConfig {
 | 
			
		||||
        multiDexEnabled = true
 | 
			
		||||
        applicationId = "com.lolo.io.onelist"
 | 
			
		||||
        compileSdk = 34
 | 
			
		||||
        minSdk = 23
 | 
			
		||||
        targetSdk = 34
 | 
			
		||||
        versionCode = versionCodeCI ?: 19
 | 
			
		||||
        versionName = "1.4.2"
 | 
			
		||||
        vectorDrawables.useSupportLibrary = true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    androidResources {
 | 
			
		||||
        generateLocaleConfig = true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    buildFeatures {
 | 
			
		||||
        viewBinding = true
 | 
			
		||||
        buildConfig = true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    ksp {
 | 
			
		||||
        arg("room.schemaLocation", "$projectDir/schemas")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    buildTypes {
 | 
			
		||||
        getByName("debug") {
 | 
			
		||||
            applicationIdSuffix = ".debug"
 | 
			
		||||
            versionNameSuffix = "-DEBUG"
 | 
			
		||||
            resValue("string", "app_name", "1ListDev")
 | 
			
		||||
        }
 | 
			
		||||
        getByName("release") {
 | 
			
		||||
            isMinifyEnabled = true
 | 
			
		||||
            isShrinkResources = true
 | 
			
		||||
 | 
			
		||||
            proguardFiles(
 | 
			
		||||
                getDefaultProguardFile("proguard-android-optimize.txt"),
 | 
			
		||||
                "proguard-rules.pro"
 | 
			
		||||
            )
 | 
			
		||||
            resValue("string", "app_name", "1List")
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    compileOptions {
 | 
			
		||||
        sourceCompatibility = JavaVersion.VERSION_17
 | 
			
		||||
        targetCompatibility = JavaVersion.VERSION_17
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
repositories {
 | 
			
		||||
    google()
 | 
			
		||||
    mavenCentral()
 | 
			
		||||
    maven { url = uri("https://jitpack.io") }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dependencies {
 | 
			
		||||
 | 
			
		||||
    // android
 | 
			
		||||
    implementation(libs.androidx.core.splashscreen)
 | 
			
		||||
    implementation(libs.androidx.preference.ktx)
 | 
			
		||||
    implementation(libs.androidx.lifecycle.extensions)
 | 
			
		||||
    implementation(libs.androidx.legacy.support.v4)
 | 
			
		||||
    implementation(libs.androidx.appcompat)
 | 
			
		||||
 | 
			
		||||
    // android - design
 | 
			
		||||
    implementation(libs.constraint.layout)
 | 
			
		||||
    implementation(libs.androidx.recyclerview)
 | 
			
		||||
    implementation(libs.flexbox)
 | 
			
		||||
    implementation(libs.material)
 | 
			
		||||
    implementation(libs.androidx.swiperefreshlayout)
 | 
			
		||||
 | 
			
		||||
    // kotlin
 | 
			
		||||
    implementation(libs.kotlinx.coroutines.core)
 | 
			
		||||
    implementation(libs.kotlin.stdlib.jdk7)
 | 
			
		||||
 | 
			
		||||
    // firebase
 | 
			
		||||
    implementation(libs.firebase.crashlytics)
 | 
			
		||||
 | 
			
		||||
    // koin di
 | 
			
		||||
    implementation(libs.koin.android)
 | 
			
		||||
    implementation(libs.koin.androidx.navigation)
 | 
			
		||||
 | 
			
		||||
    // room
 | 
			
		||||
    implementation(libs.androidx.room.runtime)
 | 
			
		||||
    implementation(libs.androidx.room.ktx)
 | 
			
		||||
    ksp(libs.androidx.room.compiler)
 | 
			
		||||
 | 
			
		||||
    // json
 | 
			
		||||
    implementation(libs.gson)
 | 
			
		||||
 | 
			
		||||
    // other libs
 | 
			
		||||
    implementation(libs.whatsnew)
 | 
			
		||||
    implementation(libs.storage)
 | 
			
		||||
    implementation(libs.advrecyclerview)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								tests/source-files/com.lolo.io.onelist/build.gradle.kts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								tests/source-files/com.lolo.io.onelist/build.gradle.kts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
plugins {
 | 
			
		||||
    alias(libs.plugins.android.application) apply false
 | 
			
		||||
    alias(libs.plugins.kotlin.android) apply false
 | 
			
		||||
    alias(libs.plugins.google.services) apply false
 | 
			
		||||
    alias(libs.plugins.firebase.crashlytics) apply false
 | 
			
		||||
    alias(libs.plugins.ksp) apply false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.register("clean", Delete::class) {
 | 
			
		||||
    delete(rootProject.layout.buildDirectory)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,58 @@
 | 
			
		|||
[versions]
 | 
			
		||||
advrecyclerview = "1.0.0"
 | 
			
		||||
appcompat = "1.6.1"
 | 
			
		||||
constraint-layout = "2.0.4"
 | 
			
		||||
crashlytics = "18.6.2"
 | 
			
		||||
firebase-crashlytics-gradle-plugin = "2.9.9"
 | 
			
		||||
flexbox = "3.0.0"
 | 
			
		||||
gson = "2.5.6"
 | 
			
		||||
kotlin = "1.9.20"
 | 
			
		||||
kotlin-coroutines = "1.6.4"
 | 
			
		||||
legacy-support-v4 = "1.0.0"
 | 
			
		||||
lifecycle-extensions = "2.2.0"
 | 
			
		||||
material = "1.11.0"
 | 
			
		||||
preference-ktx = "1.2.1"
 | 
			
		||||
recyclerview = "1.3.2"
 | 
			
		||||
splashscreen ="1.0.1"
 | 
			
		||||
koin ="3.5.0"
 | 
			
		||||
room="2.6.1"
 | 
			
		||||
storage = "1.5.5"
 | 
			
		||||
swiperefreshlayout = "1.1.0"
 | 
			
		||||
whatsnew = "0.1.7"
 | 
			
		||||
ksp-plugin="1.9.20-1.0.14"
 | 
			
		||||
 | 
			
		||||
# plugins versions
 | 
			
		||||
android-application-plugin="8.3.0"
 | 
			
		||||
kotlin-android-plugin="1.9.22"
 | 
			
		||||
google-services-plugin = "4.4.1"
 | 
			
		||||
 | 
			
		||||
[libraries]
 | 
			
		||||
advrecyclerview = { module = "com.h6ah4i.android.widget.advrecyclerview:advrecyclerview", version.ref = "advrecyclerview" }
 | 
			
		||||
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
 | 
			
		||||
androidx-core-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "splashscreen" }
 | 
			
		||||
androidx-legacy-support-v4 = { module = "androidx.legacy:legacy-support-v4", version.ref = "legacy-support-v4" }
 | 
			
		||||
androidx-lifecycle-extensions = { module = "androidx.lifecycle:lifecycle-extensions", version.ref = "lifecycle-extensions" }
 | 
			
		||||
androidx-preference-ktx = { module = "androidx.preference:preference-ktx", version.ref = "preference-ktx" }
 | 
			
		||||
androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerview" }
 | 
			
		||||
androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
 | 
			
		||||
androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" }
 | 
			
		||||
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
 | 
			
		||||
androidx-swiperefreshlayout = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version.ref = "swiperefreshlayout" }
 | 
			
		||||
constraint-layout = { module = "com.android.support.constraint:constraint-layout", version.ref = "constraint-layout" }
 | 
			
		||||
firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics", version.ref = "crashlytics" }
 | 
			
		||||
flexbox = { module = "com.google.android.flexbox:flexbox", version.ref = "flexbox" }
 | 
			
		||||
gson = { module = "org.immutables:gson", version.ref = "gson" }
 | 
			
		||||
koin-android = { module = "io.insert-koin:koin-android", version.ref = "koin" }
 | 
			
		||||
koin-androidx-navigation = { module = "io.insert-koin:koin-androidx-navigation", version.ref = "koin" }
 | 
			
		||||
kotlin-stdlib-jdk7 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk7", version.ref = "kotlin" }
 | 
			
		||||
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin-coroutines" }
 | 
			
		||||
material = { module = "com.google.android.material:material", version.ref = "material" }
 | 
			
		||||
storage = { module = "com.anggrayudi:storage", version.ref = "storage" }
 | 
			
		||||
whatsnew = { module = "io.github.tonnyl:whatsnew", version.ref = "whatsnew" }
 | 
			
		||||
 | 
			
		||||
[plugins]
 | 
			
		||||
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp-plugin" }
 | 
			
		||||
android-application = { id = "com.android.application", version.ref = "android-application-plugin" }
 | 
			
		||||
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin-android-plugin" }
 | 
			
		||||
google-services = { id = "com.google.gms.google-services", version.ref = "google-services-plugin" }
 | 
			
		||||
firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebase-crashlytics-gradle-plugin" }
 | 
			
		||||
							
								
								
									
										5
									
								
								tests/source-files/com.lolo.io.onelist/gradle/wrapper/gradle-wrapper.properties
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								tests/source-files/com.lolo.io.onelist/gradle/wrapper/gradle-wrapper.properties
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
distributionBase=GRADLE_USER_HOME
 | 
			
		||||
distributionPath=wrapper/dists
 | 
			
		||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
 | 
			
		||||
zipStoreBase=GRADLE_USER_HOME
 | 
			
		||||
zipStorePath=wrapper/dists
 | 
			
		||||
							
								
								
									
										9
									
								
								tests/source-files/com.lolo.io.onelist/settings.gradle
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tests/source-files/com.lolo.io.onelist/settings.gradle
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
pluginManagement {
 | 
			
		||||
    repositories {
 | 
			
		||||
        google()
 | 
			
		||||
        mavenCentral()
 | 
			
		||||
        gradlePluginPortal()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
include 'app'
 | 
			
		||||
							
								
								
									
										47
									
								
								tests/source-files/org.piepmeyer.gauguin/build.gradle.kts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								tests/source-files/org.piepmeyer.gauguin/build.gradle.kts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
import java.net.URI
 | 
			
		||||
 | 
			
		||||
buildscript {
 | 
			
		||||
    dependencies {
 | 
			
		||||
        classpath("com.android.tools.build:gradle:8.6.0")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
plugins {
 | 
			
		||||
    alias(libs.plugins.android.application) apply false
 | 
			
		||||
    alias(libs.plugins.android.library) apply false
 | 
			
		||||
    alias(libs.plugins.kotlin.android) apply false
 | 
			
		||||
    alias(libs.plugins.kotlin.jvm) apply false
 | 
			
		||||
    alias(libs.plugins.sonarqube)
 | 
			
		||||
    alias(libs.plugins.ktlint)
 | 
			
		||||
    alias(libs.plugins.ksp)
 | 
			
		||||
    alias(libs.plugins.roborazzi) apply false
 | 
			
		||||
    alias(libs.plugins.gms) apply false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sonarqube {
 | 
			
		||||
    properties {
 | 
			
		||||
        property("sonar.projectKey", "org.piepmeyer.gauguin")
 | 
			
		||||
        property("sonar.organization", "meikpiep")
 | 
			
		||||
        property("sonar.verbose", "true")
 | 
			
		||||
        property("sonar.host.url", "https://sonarcloud.io")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.sonar {
 | 
			
		||||
    onlyIf("There is no property 'buildserver'") {
 | 
			
		||||
        project.hasProperty("buildserver")
 | 
			
		||||
    }
 | 
			
		||||
    dependsOn(":gauguin-app:lint")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
allprojects {
 | 
			
		||||
    repositories {
 | 
			
		||||
        mavenCentral()
 | 
			
		||||
        google()
 | 
			
		||||
        maven { url = URI("https://jitpack.io") }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
subprojects {
 | 
			
		||||
    apply(plugin = "org.jlleitschuh.gradle.ktlint")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										91
									
								
								tests/source-files/org.piepmeyer.gauguin/libs.versions.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								tests/source-files/org.piepmeyer.gauguin/libs.versions.toml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,91 @@
 | 
			
		|||
[versions]
 | 
			
		||||
 | 
			
		||||
kotlin = "1.9.23"
 | 
			
		||||
koin = "3.5.6"
 | 
			
		||||
koin-annotations="1.3.1"
 | 
			
		||||
kotest = "5.9.1"
 | 
			
		||||
kotest-extensions = "1.3.0"
 | 
			
		||||
kotlin-coroutines = "1.8.1"
 | 
			
		||||
android-gradle-plugin = "8.6.0"
 | 
			
		||||
androidUiTestingUtils = "2.3.3"
 | 
			
		||||
roborazzi = "1.26.0"
 | 
			
		||||
 | 
			
		||||
[libraries]
 | 
			
		||||
 | 
			
		||||
kotlin-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlin-coroutines" }
 | 
			
		||||
kotlin-coroutines-debug = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-debug", version.ref = "kotlin-coroutines" }
 | 
			
		||||
kotlin-serialization = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version = "1.6.3" }
 | 
			
		||||
 | 
			
		||||
logging-kotlin = { group = "io.github.oshai", name = "kotlin-logging-jvm", version = "6.0.9" }
 | 
			
		||||
logging-slf = { group = "org.slf4j", name = "slf4j-api", version = "2.0.13" }
 | 
			
		||||
logging-logback-android = { group = "com.github.tony19", name = "logback-android", version = "3.0.0" }
 | 
			
		||||
logging-logback-kotlin = { group = "ch.qos.logback", name = "logback-classic", version = "1.5.6" }
 | 
			
		||||
 | 
			
		||||
android-material = { group = "com.google.android.material", name = "material", version = "1.12.0" }
 | 
			
		||||
 | 
			
		||||
androidx-annotation = { group = "androidx.annotation", name = "annotation", version = "1.8.2" }
 | 
			
		||||
androidx-ktx = { group = "androidx.core", name = "core-ktx", version = "1.13.1" }
 | 
			
		||||
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version = "2.1.4" }
 | 
			
		||||
androidx-drawerlayout = { group = "androidx.drawerlayout", name = "drawerlayout", version = "1.2.0" }
 | 
			
		||||
androidx-fragment = { group = "androidx.fragment", name = "fragment-ktx", version = "1.8.3" }
 | 
			
		||||
androidx-gridlayout = { group = "androidx.gridlayout", name = "gridlayout", version = "1.0.0" }
 | 
			
		||||
androidx-lifecycle-runtime = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version = "2.8.5" }
 | 
			
		||||
androidx-lifecycle-viewmodel = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version = "2.8.5" }
 | 
			
		||||
androidx-preference = { group = "androidx.preference", name = "preference-ktx", version = "1.2.1" }
 | 
			
		||||
androidx-recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version = "1.3.2" }
 | 
			
		||||
androidx-transition = { group = "androidx.transition", name = "transition", version = "1.5.1" }
 | 
			
		||||
androidx-window = { group = "androidx.window", name = "window", version = "1.3.0" }
 | 
			
		||||
androidx-window-core = { group = "androidx.window", name = "window-core", version = "1.3.0" }
 | 
			
		||||
 | 
			
		||||
androidx-test-junit-ktx = { group = "androidx.test.ext", name = "junit-ktx", version = "1.2.1" }
 | 
			
		||||
androidx-test-rules = { group = "androidx.test", name = "rules", version = "1.6.1" }
 | 
			
		||||
androidx-test-runner = { group = "androidx.test", name = "runner", version = "1.6.2" }
 | 
			
		||||
 | 
			
		||||
koin-core = { group = "io.insert-koin", name = "koin-core", version.ref = "koin" }
 | 
			
		||||
koin-annotations = { group = "io.insert-koin", name = "koin-annotations", version.ref = "koin-annotations" }
 | 
			
		||||
koin-ksp-compiler = { group = "io.insert-koin", name = "koin-ksp-compiler", version.ref = "koin-annotations" }
 | 
			
		||||
koin-test = { group = "io.insert-koin", name = "koin-test", version.ref = "koin" }
 | 
			
		||||
koin-android = { group = "io.insert-koin", name = "koin-android", version.ref = "koin" }
 | 
			
		||||
 | 
			
		||||
kotest-runner = { group = "io.kotest", name = "kotest-runner-junit5", version.ref = "kotest" }
 | 
			
		||||
kotest-assertions = { group = "io.kotest", name = "kotest-assertions-core", version.ref = "kotest" }
 | 
			
		||||
kotest-parametrizedtests = { group = "io.kotest", name = "kotest-framework-datatest", version.ref = "kotest" }
 | 
			
		||||
kotest-koin = { group = "io.kotest.extensions", name = "kotest-extensions-koin", version.ref = "kotest-extensions" }
 | 
			
		||||
 | 
			
		||||
test-mockk = { group = "io.mockk", name = "mockk", version = "1.13.11" }
 | 
			
		||||
 | 
			
		||||
androiduitestingutils-utils = { group = "com.github.sergio-sastre.AndroidUiTestingUtils", name = "utils", version.ref = "androidUiTestingUtils" }
 | 
			
		||||
androiduitestingutils-robolectric = { group = "com.github.sergio-sastre.AndroidUiTestingUtils", name = "robolectric", version.ref = "androidUiTestingUtils" }
 | 
			
		||||
roboelectric = { group = "org.robolectric", name = "robolectric", version = "4.13" }
 | 
			
		||||
roborazzi = { group = "io.github.takahirom.roborazzi", name = "roborazzi", version.ref = "roborazzi" }
 | 
			
		||||
roborazzi-junit = { group = "io.github.takahirom.roborazzi", name = "roborazzi-junit-rule", version.ref = "roborazzi" }
 | 
			
		||||
junit-vintage-engine = { group = "org.junit.vintage", name = "junit-vintage-engine", version = "5.10.3" }
 | 
			
		||||
 | 
			
		||||
thirdparty-konfetti = { group = "nl.dionsegijn", name = "konfetti-xml", version = "2.0.4" }
 | 
			
		||||
#thirdparty-ferriswheel = { group = "ru.github.igla", name = "ferriswheel", version = "1.2" }
 | 
			
		||||
thirdparty-navigationdrawer = { group = "com.mikepenz", name = "materialdrawer", version = "9.0.2" }
 | 
			
		||||
thirdparty-balloon = { group = "com.github.skydoves", name = "balloon", version = "1.6.7" }
 | 
			
		||||
thirdparty-vico = { group = "com.patrykandpatrick.vico", name = "views", version = "2.0.0-alpha.25" }
 | 
			
		||||
thirdparty-androidplot = { group = "com.androidplot", name = "androidplot-core", version = "1.5.11" }
 | 
			
		||||
thirdparty-leakcanary = { group = "com.squareup.leakcanary", name = "leakcanary-android", version = "2.14" }
 | 
			
		||||
 | 
			
		||||
[plugins]
 | 
			
		||||
 | 
			
		||||
android-application = { id = "com.android.application", version.ref = "android-gradle-plugin" }
 | 
			
		||||
android-library = { id = "com.android.library", version.ref = "android-gradle-plugin" }
 | 
			
		||||
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
 | 
			
		||||
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
 | 
			
		||||
sonarqube = { id = "org.sonarqube", version = "5.0.0.4638" }
 | 
			
		||||
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version = "12.1.1" }
 | 
			
		||||
ksp = { id = "com.google.devtools.ksp", version = "1.9.23-1.0.20" }
 | 
			
		||||
roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" }
 | 
			
		||||
gms = { id = "com.google.gms.google-services", version = "1" }
 | 
			
		||||
 | 
			
		||||
[bundles]
 | 
			
		||||
 | 
			
		||||
logging = ["logging-kotlin", "logging-slf"]
 | 
			
		||||
kotest = ["kotest-runner", "kotest-assertions", "kotest-parametrizedtests", "kotest-koin"]
 | 
			
		||||
koin = ["koin-core", "koin-annotations", "koin-ksp-compiler"]
 | 
			
		||||
androidx-test = ["androidx-test-junit-ktx", "androidx-test-rules", "androidx-test-runner"]
 | 
			
		||||
screenshotTests = ["androiduitestingutils-utils", "androiduitestingutils-robolectric", "roboelectric", "roborazzi", "roborazzi-junit", "junit-vintage-engine"]
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										24
									
								
								tests/source-files/org.piepmeyer.gauguin/settings.gradle.kts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								tests/source-files/org.piepmeyer.gauguin/settings.gradle.kts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
pluginManagement {
 | 
			
		||||
    repositories {
 | 
			
		||||
        google()
 | 
			
		||||
        mavenCentral()
 | 
			
		||||
        gradlePluginPortal()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dependencyResolutionManagement {
 | 
			
		||||
    versionCatalogs {
 | 
			
		||||
        create("libs") {
 | 
			
		||||
            from(files("libs.versions.toml"))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
plugins {
 | 
			
		||||
    id("org.gradle.toolchains.foojay-resolver-convention") version ("0.8.0")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rootProject.name = "gauguin"
 | 
			
		||||
 | 
			
		||||
include(":gauguin-app")
 | 
			
		||||
include(":gauguin-core")
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue