|  | 
|  | 1 | +"""ARVO data management module. | 
|  | 2 | +
 | 
|  | 3 | +This module provides data management functions for ARVO reproducer, | 
|  | 4 | +including configuration mappings and Docker/build script fixes. | 
|  | 5 | +""" | 
|  | 6 | + | 
|  | 7 | +from pathlib import Path | 
|  | 8 | +from typing import Any, Dict, Tuple | 
|  | 9 | +from datetime import datetime | 
|  | 10 | +from hacks import get_project_hack | 
|  | 11 | + | 
|  | 12 | +from arvo_utils import (DockerfileModifier, CHANGED_KEY, CHANGED_TYPE, | 
|  | 13 | +                        GLOBAL_STR_REPLACE, UPDATE_TABLE) | 
|  | 14 | + | 
|  | 15 | + | 
|  | 16 | +def update_resource_info(item_name: str, item_url: str, | 
|  | 17 | +                         item_type: str) -> Tuple[str, str, str]: | 
|  | 18 | +  """Update resource information based on configuration tables. | 
|  | 19 | +     | 
|  | 20 | +    Args: | 
|  | 21 | +        item_name: Name of the resource item. | 
|  | 22 | +        item_url: URL of the resource. | 
|  | 23 | +        item_type: Type of the resource. | 
|  | 24 | +         | 
|  | 25 | +    Returns: | 
|  | 26 | +        Tuple of (updated_name, updated_url, updated_type). | 
|  | 27 | +    """ | 
|  | 28 | +  if item_name in CHANGED_KEY: | 
|  | 29 | +    item_name = CHANGED_KEY[item_name] | 
|  | 30 | + | 
|  | 31 | +  if item_name in UPDATE_TABLE: | 
|  | 32 | +    resource_type = CHANGED_TYPE.get(item_name, 'git') | 
|  | 33 | +    return item_name, UPDATE_TABLE[item_name], resource_type | 
|  | 34 | +  else: | 
|  | 35 | +    return item_name, item_url, item_type | 
|  | 36 | + | 
|  | 37 | + | 
|  | 38 | +def dockerfile_cleaner(dockerfile_path: str | Path) -> None: | 
|  | 39 | +  """Clean dockerfile by removing git branch-specific arguments. | 
|  | 40 | +     | 
|  | 41 | +    Args: | 
|  | 42 | +        dockerfile_path: Path to the Dockerfile to clean. | 
|  | 43 | +    """ | 
|  | 44 | +  dft = DockerfileModifier(dockerfile_path) | 
|  | 45 | +  dft.replace(r'(--single-branch\s+)', "")  # --single-branch | 
|  | 46 | +  dft.replace(r'(--branch\s+\S+\s+|-b\s\S+\s+|--branch=\S+\s+)', | 
|  | 47 | +              "")  # remove --branch or -b | 
|  | 48 | +  dft.flush() | 
|  | 49 | + | 
|  | 50 | + | 
|  | 51 | +def fix_dockerfile(dockerfile_path: str | Path, | 
|  | 52 | +                   project: str | None = None, | 
|  | 53 | +                   commit_date: datetime | None = None) -> bool: | 
|  | 54 | +  """Fix the dockerfile for specific projects and general issues. | 
|  | 55 | +     | 
|  | 56 | +    Args: | 
|  | 57 | +        dockerfile_path: Path to the Dockerfile to fix. | 
|  | 58 | +        project: Name of the project for project-specific fixes. | 
|  | 59 | +        commit_date: Target commit date (required for some projects like GDAL). | 
|  | 60 | +         | 
|  | 61 | +    Returns: | 
|  | 62 | +        True if fixes were applied successfully, False otherwise. | 
|  | 63 | +    """ | 
|  | 64 | + | 
|  | 65 | +  dockerfile_cleaner(dockerfile_path) | 
|  | 66 | +  dft = DockerfileModifier(dockerfile_path) | 
|  | 67 | + | 
|  | 68 | +  # Some dockerfile forgets to apt update before apt install | 
|  | 69 | +  # and we have to install/set ca-certificate/git sslVerify to avoid | 
|  | 70 | +  # certificates issues | 
|  | 71 | +  # TODO: improve regex | 
|  | 72 | +  dft.replace_once( | 
|  | 73 | +      r'RUN apt', "RUN apt update -y && apt install git ca-certificates -y && " | 
|  | 74 | +      "git config --global http.sslVerify false && " | 
|  | 75 | +      "git config --global --add safe.directory '*'\nRUN apt") | 
|  | 76 | +  dft.str_replace_all(GLOBAL_STR_REPLACE) | 
|  | 77 | + | 
|  | 78 | +  # Apply project-specific hacks that solve building/compiling problems | 
|  | 79 | +  if project: | 
|  | 80 | +    hack = get_project_hack(project) | 
|  | 81 | +    if hack: | 
|  | 82 | +      # Pass commit_date to the hack if it needs it | 
|  | 83 | +      if hasattr(hack, 'set_commit_date') and commit_date: | 
|  | 84 | +        hack.set_commit_date(commit_date) | 
|  | 85 | +      if not hack.apply_dockerfile_fixes(dft): | 
|  | 86 | +        return False | 
|  | 87 | + | 
|  | 88 | +  dft.clean_comments() | 
|  | 89 | +  return dft.flush() | 
|  | 90 | + | 
|  | 91 | + | 
|  | 92 | +def fix_build_script(file_path: Path, project_name: str) -> bool: | 
|  | 93 | +  """Fix the build script for specific projects. | 
|  | 94 | +     | 
|  | 95 | +    Args: | 
|  | 96 | +        file_path: Path to the build script file. | 
|  | 97 | +        project_name: Name of the project. | 
|  | 98 | +         | 
|  | 99 | +    Returns: | 
|  | 100 | +        True if fixes were applied successfully, False otherwise. | 
|  | 101 | +    """ | 
|  | 102 | +  if not file_path.exists(): | 
|  | 103 | +    return True | 
|  | 104 | + | 
|  | 105 | +  dft = DockerfileModifier(file_path) | 
|  | 106 | + | 
|  | 107 | +  # Apply project-specific build script hacks | 
|  | 108 | +  hack = get_project_hack(project_name) | 
|  | 109 | +  if hack and not hack.apply_build_script_fixes(dft): | 
|  | 110 | +    return False | 
|  | 111 | + | 
|  | 112 | +  return dft.flush() | 
|  | 113 | + | 
|  | 114 | + | 
|  | 115 | +def extra_scripts(project_name: str, source_dir: Path) -> bool: | 
|  | 116 | +  """Execute extra scripts for specific projects. | 
|  | 117 | +     | 
|  | 118 | +    This function allows us to modify build.sh scripts and other stuff | 
|  | 119 | +    to modify the compiling setting. | 
|  | 120 | +     | 
|  | 121 | +    Args: | 
|  | 122 | +        project_name: Name of the project. | 
|  | 123 | +        source_dir: Path to the source directory. | 
|  | 124 | +         | 
|  | 125 | +    Returns: | 
|  | 126 | +        True if scripts executed successfully, False otherwise. | 
|  | 127 | +    """ | 
|  | 128 | +  # Apply project-specific extra fixes | 
|  | 129 | +  hack = get_project_hack(project_name) | 
|  | 130 | +  if hack and not hack.apply_extra_fixes(source_dir): | 
|  | 131 | +    return False | 
|  | 132 | +  return True | 
|  | 133 | + | 
|  | 134 | + | 
|  | 135 | +def special_component(project_name: str, item_key: str, item: Dict[str, Any], | 
|  | 136 | +                      dockerfile: str | Path) -> bool: | 
|  | 137 | +  """Check if a component requires special handling. | 
|  | 138 | +     | 
|  | 139 | +    TODO: Theoretically, we can remove this func since other parts gonna | 
|  | 140 | +    handle the submodule, but not tested. | 
|  | 141 | +    These components are submodules, but their info are in srcmap. | 
|  | 142 | +     | 
|  | 143 | +    Args: | 
|  | 144 | +        project_name: Name of the project. | 
|  | 145 | +        item_key: Key of the item in srcmap. | 
|  | 146 | +        item: Item data from srcmap. | 
|  | 147 | +        dockerfile: Path to the dockerfile. | 
|  | 148 | +         | 
|  | 149 | +    Returns: | 
|  | 150 | +        True if component should be skipped, False otherwise. | 
|  | 151 | +    """ | 
|  | 152 | +  # These components are submodules, but their info are in srcmap | 
|  | 153 | +  if project_name == 'libressl' and item_key == '/src/libressl/openbsd': | 
|  | 154 | +    return False | 
|  | 155 | + | 
|  | 156 | +  if project_name == 'gnutls' and item_key == '/src/gnutls/nettle': | 
|  | 157 | +    # Just Ignore since we have submodule update --init | 
|  | 158 | +    with open(dockerfile, encoding='utf-8') as f: | 
|  | 159 | +      dt = f.read() | 
|  | 160 | +    if item['rev'] not in dt: | 
|  | 161 | +      return True | 
|  | 162 | +    else: | 
|  | 163 | +      return False | 
|  | 164 | + | 
|  | 165 | +  return False | 
|  | 166 | + | 
|  | 167 | + | 
|  | 168 | +def skip_component(project_name: str, item_name: str) -> bool: | 
|  | 169 | +  """Check if a component should be skipped during processing. | 
|  | 170 | +     | 
|  | 171 | +    TODO: solve the submodule problem in a decent way | 
|  | 172 | +     | 
|  | 173 | +    Args: | 
|  | 174 | +        project_name: Name of the project. | 
|  | 175 | +        item_name: Name of the item/component. | 
|  | 176 | +         | 
|  | 177 | +    Returns: | 
|  | 178 | +        True if component should be skipped, False otherwise. | 
|  | 179 | +    """ | 
|  | 180 | +  NO_OPERATION = ( | 
|  | 181 | +      "/src", | 
|  | 182 | +      "/src/LPM/external.protobuf/src/external.protobuf", | 
|  | 183 | +      "/src/libprotobuf-mutator/build/external.protobuf/src/external.protobuf", | 
|  | 184 | +  ) | 
|  | 185 | +  item_name = item_name.strip(" ") | 
|  | 186 | + | 
|  | 187 | +  # Special for skia, Skip since they are done by submodule init | 
|  | 188 | +  if project_name in ['skia', 'skia-ftz']: | 
|  | 189 | +    if item_name.startswith("/src/skia/"): | 
|  | 190 | +      return True | 
|  | 191 | + | 
|  | 192 | +  if item_name in NO_OPERATION: | 
|  | 193 | +    return True | 
|  | 194 | + | 
|  | 195 | +  return False | 
|  | 196 | + | 
|  | 197 | + | 
|  | 198 | +if __name__ == "__main__": | 
|  | 199 | +  pass | 
0 commit comments