diff --git a/src/android_builder/ForkAndRun.cpp b/src/android_builder/ForkAndRun.cpp index ef9c47e7..55ffc866 100644 --- a/src/android_builder/ForkAndRun.cpp +++ b/src/android_builder/ForkAndRun.cpp @@ -108,13 +108,13 @@ bool ForkAndRun::execute() { Selector::Mode::READ); selector.add( python_pipe.readEnd(), - [python_pipe] { + [python_pipe, this] { BufferType buf{}; ssize_t bytes_read = read(python_pipe.readEnd(), buf.data(), buf.size() - 1); if (bytes_read >= 0) { - printf("Python output: "); - fputs(buf.data(), stdout); + onNewStdoutBuffer(buf); + buf.fill(0); } }, Selector::Mode::READ); diff --git a/src/android_builder/scripts/build_rom_utils.py b/src/android_builder/scripts/build_rom_utils.py index 84f6e3c6..ef567b50 100644 --- a/src/android_builder/scripts/build_rom_utils.py +++ b/src/android_builder/scripts/build_rom_utils.py @@ -21,23 +21,47 @@ def find_vendor_str() -> str: def build_rom(device: str, variant: str, target: str, jobs: int) -> bool: vendor = find_vendor_str() - success = False if vendor is None: print('Couldn\'t find vendor') return False - shell_process = subprocess.Popen(['bash'], stdin=subprocess.PIPE, text=True) + shell_process = subprocess.Popen(['bash'], stdin=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) print('Writing . build/envsetup.sh') shell_process.stdin.write('. build/envsetup.sh\n') + if os.getenv('USE_CCACHE') is not None: + print('ccache is useless, unset USE_CCACHE') + os.unsetenv('USE_CCACHE') print(f'Writing lunch {vendor}_{device}-{variant}') shell_process.stdin.write(f'lunch {vendor}_{device}-{variant}\n') + shell_process.stdin.write('echo "exit code: $?\n') + shell_process.stdin.flush() + print('Waiting for lunch command result...') + while True: + line = process.stdout.readline() + if line.startswith("exit code:"): + # Extract the exit code from the line + exit_code = int(line.strip().split()[-1]) + break + print(line) + + if exit_code != 0: + print(f'Error: lunch command failed with exit code {exit_code}') + print(shell_process.stderr.read()) + return False + + # Remap to original stdout/stderr + shell_process.stdout.close() + shell_process.stderr.close() + shell_process.stdout = os.fdopen(os.dup(1), 'w') + shell_process.stderr = os.fdopen(os.dup(2), 'w') + + # Start the build process print(f'Writing m {target} -j{jobs}') shell_process.stdin.write(f'm {target} -j{jobs}\n') shell_process.stdin.flush() shell_process.stdin.close() print('Now waiting...') shell_process.wait() - success = shell_process.returncode == 0 - - return success \ No newline at end of file + return shell_process.returncode == 0 \ No newline at end of file diff --git a/src/android_builder/scripts/upload_file.py b/src/android_builder/scripts/upload_file.py index 16575f9a..85bcd41f 100644 --- a/src/android_builder/scripts/upload_file.py +++ b/src/android_builder/scripts/upload_file.py @@ -38,10 +38,11 @@ def upload_to_gofile(device_name, file_prefix) -> str: print(f"SSL certificate verification failed: {e}") dir_path = os.path.dirname(os.path.realpath(__file__)) out, err = subprocess_utils.run_command_with_output(f'bash {dir_path}/upload_file.bash {file_to_upload}') - return f""" - STDOUT: {out} - STDERR: {err} - """ + if out is None: + with open('upload_err.txt', 'w') as f: + f.write(err) + return f"An error occurred while uploading the file. See upload_err.txt for details." + return out # Check the response from GoFile if response.status_code == 200: diff --git a/src/android_builder/tasks/ROMBuildTask.cpp b/src/android_builder/tasks/ROMBuildTask.cpp index a547a4a4..d507bef0 100644 --- a/src/android_builder/tasks/ROMBuildTask.cpp +++ b/src/android_builder/tasks/ROMBuildTask.cpp @@ -4,6 +4,7 @@ #include #include +#include bool ROMBuildTask::runFunction() { auto dataShmem = @@ -62,15 +63,19 @@ bool ROMBuildTask::runFunction() { LOG(ERROR) << "ROM build failed"; std::ifstream errorLog(kErrorLogFile.data()); if (errorLog.is_open()) { + static std::regex ansi_escape_code_pattern( + R"(\x1B\[[0-9;]*[A-Za-z])"); + std::string errorLogContent( (std::istreambuf_iterator(errorLog)), std::istreambuf_iterator()); - if (errorLogContent.find("FAILED:") != std::string::npos) { + const auto commandIdx = errorLogContent.find("Command:"); + if (commandIdx != std::string::npos) { // Ninja error - resultdata->setMessage(errorLogContent.substr(0, - errorLogContent.find_first_of("Command:"))); + resultdata->setMessage(errorLogContent.substr(0, commandIdx)); } else { // Probably makefile? + std::regex_replace(errorLogContent, ansi_escape_code_pattern, ""); resultdata->setMessage(errorLogContent); } } else { @@ -93,7 +98,7 @@ int ROMBuildTask::guessJobCount() { } total_memory /= Multiplier; // Convert to GB LOG(INFO) << "Total memory: " << total_memory << "GB"; - jobCount = static_cast(sqrt(total_memory) * 2); + jobCount = static_cast(sqrt(total_memory)); LOG(INFO) << "Using job count: " << jobCount; }); return jobCount; @@ -111,7 +116,8 @@ void ROMBuildTask::onNewStdoutBuffer(ForkAndRun::BufferType& buffer) { buildInfoBuffer << "Last updated on: " << fromTP(now) << std::endl; buildInfoBuffer << "Target ROM: " << data.rConfig.name << ", branch: " << data.rConfig.branch << std::endl; - buildInfoBuffer << "Target device: " << data.bConfig.device << std::endl; + buildInfoBuffer << "Target device: " << data.bConfig.device + << std::endl; buildInfoBuffer << "Job count: " << guessJobCount(); if (_get_used_mem->call(nullptr, &memUsage)) { buildInfoBuffer << ", memory usage: " << memUsage << "%"; diff --git a/src/android_builder/tasks/RepoSyncTask.cpp b/src/android_builder/tasks/RepoSyncTask.cpp index 4556d412..ddd047a9 100644 --- a/src/android_builder/tasks/RepoSyncTask.cpp +++ b/src/android_builder/tasks/RepoSyncTask.cpp @@ -35,31 +35,37 @@ bool tryToMakeItMine(const PerBuildData& data) { RAIIGit raii; const auto git_error_last_str = [] { return git_error_last()->message; }; int ret = 0; + constexpr std::string_view kRemoteRepoName = "origin"; git_repository* repo = nullptr; git_reference* head_ref = nullptr; + git_reference* target_ref = nullptr; + git_reference* target_remote_ref = nullptr; const char* current_branch = nullptr; + const char* remote_url = nullptr; git_object* treeish = nullptr; git_remote* remote = nullptr; - const char* remote_url = nullptr; + git_commit* commit = nullptr; + git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; ret = git_repository_open(&repo, RepoSyncTask::kLocalManifestPath.data()); if (ret != 0) { - LOG(ERROR) << "Failed to open repository"; + LOG(ERROR) << "Failed to open repository: " << git_error_last_str(); return false; } raii.addCleanup([repo] { git_repository_free(repo); }); - ret = git_remote_lookup(&remote, repo, "origin"); + ret = git_remote_lookup(&remote, repo, kRemoteRepoName.data()); if (ret != 0) { - LOG(ERROR) << "Failed to lookup remote origin"; + LOG(ERROR) << "Failed to lookup remote origin: " + << git_error_last_str(); return false; } raii.addCleanup([remote] { git_remote_free(remote); }); remote_url = git_remote_url(remote); if (remote_url == nullptr) { - LOG(ERROR) << "Remote origin URL is null"; + LOG(ERROR) << "Remote origin URL is null: " << git_error_last_str(); return false; } LOG(INFO) << "Remote origin URL: " << remote_url; @@ -71,7 +77,7 @@ bool tryToMakeItMine(const PerBuildData& data) { ret = git_repository_head(&head_ref, repo); if (ret != 0) { - LOG(ERROR) << "Failed to get HEAD reference"; + LOG(ERROR) << "Failed to get HEAD reference: " << git_error_last_str(); return false; } raii.addCleanup([head_ref] { git_reference_free(head_ref); }); @@ -80,26 +86,99 @@ bool tryToMakeItMine(const PerBuildData& data) { LOG(INFO) << "Current branch: " << current_branch; CStringLifetime branch_name = data.bConfig.local_manifest.branch; + // Check if the branch is the one we're interested in if (data.bConfig.local_manifest.branch != current_branch) { - LOG(INFO) << "Switching to branch: " - << data.bConfig.local_manifest.branch; + LOG(INFO) << "Switching to branch: " << branch_name.get(); + struct { + // refs/heads/*branch* + std::string local; + std::string remote; + } target_ref_name; + target_ref_name.local += "refs/heads/"; + target_ref_name.local += branch_name.get(); + target_ref_name.remote += "refs/remotes/"; + target_ref_name.remote += kRemoteRepoName.data(); + target_ref_name.remote += "/"; + target_ref_name.remote += branch_name.get(); - ret = git_revparse_single(&treeish, repo, branch_name); + // Try to find the branch ref in the repository + ret = git_reference_lookup(&target_ref, repo, + target_ref_name.local.c_str()); if (ret != 0) { - LOG(ERROR) << "Failed to find the branch"; - return false; - } - raii.addCleanup([treeish] { git_object_free(treeish); }); + LOG(ERROR) << "Failed to find the branch ref: " + << git_error_last_str(); - ret = git_checkout_tree(repo, treeish, nullptr); - if (ret != 0) { - LOG(ERROR) << "Failed to checkout tree"; - return false; + // Maybe remote has it? + ret = git_remote_fetch(remote, nullptr, nullptr, nullptr); + if (ret != 0) { + LOG(ERROR) << "Failed to fetch remote: " + << git_error_last_str(); + return false; + } + + // Now try to find the branch in the remote + ret = git_reference_lookup(&target_remote_ref, repo, + target_ref_name.remote.c_str()); + if (ret != 0) { + LOG(ERROR) << "Failed to find the branch " + "in the remote: " + << git_error_last_str(); + return false; + } + raii.addCleanup( + [target_remote_ref] { git_reference_free(target_remote_ref); }); + + // Get the commit of the target branch ref + ret = git_commit_lookup(&commit, repo, + git_reference_target(target_remote_ref)); + if (ret != 0) { + LOG(ERROR) << "Failed to find the commit: " + << git_error_last_str(); + return false; + } + raii.addCleanup([commit] { git_commit_free(commit); }); + + // Create the local branch ref pointing to the commit + ret = git_branch_create(&target_ref, repo, branch_name.get(), + commit, 0); + if (ret != 0) { + LOG(ERROR) << "Failed to create branch: " + << git_error_last_str(); + return false; + } + raii.addCleanup([target_ref] { git_reference_free(target_ref); }); + + // Checkout the local branch + ret = git_checkout_head(repo, &checkout_opts); + if (ret != 0) { + LOG(ERROR) << "Failed to checkout head: " + << git_error_last_str(); + return false; + } + + LOG(INFO) << "Success on checking out remote branch"; + } else { + raii.addCleanup([target_ref] { git_reference_free(target_ref); }); + + // Get the object of the target branch ref + ret = git_reference_peel(&treeish, target_ref, GIT_OBJECT_TREE); + if (ret != 0) { + LOG(ERROR) << "Failed to find the branch: " + << git_error_last_str(); + return false; + } + raii.addCleanup([treeish] { git_object_free(treeish); }); + + ret = git_checkout_tree(repo, treeish, nullptr); + if (ret != 0) { + LOG(ERROR) << "Failed to checkout tree: " + << git_error_last_str(); + return false; + } } - ret = git_repository_set_head( - repo, ("refs/heads/" + std::string(branch_name)).c_str()); + ret = git_repository_set_head(repo, target_ref_name.local.c_str()); if (ret != 0) { - LOG(ERROR) << "Failed to set HEAD"; + LOG(ERROR) << "Failed to set HEAD: " << git_error_last_str(); return false; } } else { diff --git a/src/command_modules/runtime/cmd_RomBuild.cpp b/src/command_modules/runtime/cmd_RomBuild.cpp index dd978866..c0db0af9 100644 --- a/src/command_modules/runtime/cmd_RomBuild.cpp +++ b/src/command_modules/runtime/cmd_RomBuild.cpp @@ -164,6 +164,11 @@ void upload(PerBuildData data, const Bot& bot, const Message::Ptr& message) { bot_editMessage(bot, uploadmsg, "Could'nt initialize upload"); } else { bot_editMessage(bot, uploadmsg, uploadResult.getMessage()); + if (uploadResult.value == PerBuildData::Result::ERROR_FATAL) { + bot.getApi().sendDocument( + message->chat->id, + TgBot::InputFile::fromFile("upload_err.txt", "text/plain")); + } } } } // namespace diff --git a/src/libos/libfs.cpp b/src/libos/libfs.cpp index 71296820..dbf39c5c 100644 --- a/src/libos/libfs.cpp +++ b/src/libos/libfs.cpp @@ -100,7 +100,6 @@ std::filesystem::path FS::getPathForType(PathType type) { } if (ok) { path.make_preferred(); - if (type != PathType::HOME) makeRelativeToCWD(path); } else { LOG(ERROR) << "Could not find path for type " << static_cast(type); }