Skip to content

03.4 function ‐ 04

Eshan Roy edited this page Dec 20, 2024 · 1 revision

Full Code:

void SnigdhaOSBlackbox::doUpdate() {
    // Check if the environment variable "SNIGDHAOS_BLACKBOX_SELFUPDATE" is set
    if (qEnvironmentVariableIsSet("SNIGDHAOS_BLACKBOX_SELFUPDATE")) {
        // If the variable is set, update the state to "SELECT" to let the application know it's in the self-update state
        updateState(State::SELECT);
        return;  // Exit the function early, as we don't want to proceed with the update if self-update is already in progress
    }

    // Create a new QProcess object, which is used to run external processes (like shell commands)
    auto process = new QProcess(this);

    // Create a temporary file that will be used during the update process
    QTemporaryFile* file = new QTemporaryFile(this);
    file->open();  // Open the temporary file for reading/writing
    file->setAutoRemove(true);  // Set the file to automatically delete itself once it's closed

    // Start a new process to run the terminal command for updating the system using pacman
    process->start("/usr/lib/snigdhaos/launch-terminal", 
                    QStringList() << QString("sudo pacman -Syyu 2>&1 && rm \"" + file->fileName() + "\"; read -p 'Press Enter↵ to Exit'"));

    // When the QProcess finishes, this lambda function is triggered
    connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), 
            this, [this, process, file](int exitcode, QProcess::ExitStatus status) {
        
        // Cleanup: Delete the QProcess and the temporary file after the process has finished
        process->deleteLater();
        file->deleteLater();

        // Check if the process completed successfully (exitcode == 0)
        // Additionally, verify that the temporary file no longer exists, meaning the update process completed as expected
        if (exitcode == 0 && !file->exists()) {
            // If successful, restart the application with the "POST_UPDATE" state (indicating the update was successful)
            relaunchSelf("POST_UPDATE");
        } else {
            // If the process failed, or the file still exists (indicating the update didn't finish properly),
            // restart the application with the "UPDATE_RETRY" state, asking the user to retry the update
            relaunchSelf("UPDATE_RETRY");
        }
    });
}

Detailed Breakdown:

  1. Check for Self-Update Environment Variable:

    if (qEnvironmentVariableIsSet("SNIGDHAOS_BLACKBOX_SELFUPDATE")) {
        updateState(State::SELECT);
        return;
    }
    • The first line checks if the environment variable SNIGDHAOS_BLACKBOX_SELFUPDATE is set.
    • Environment variables are often used to manage application states or configurations. Here, it's being used to indicate whether the application is currently undergoing a self-update process.
    • If the variable is set, the application enters a specific state (State::SELECT), and the function returns early, preventing further execution of the update process.
    • The function terminates here if the update is already in progress, as the logic doesn't need to run again.
  2. Creating a QProcess to Launch an External Command:

    auto process = new QProcess(this);
    • QProcess is a Qt class that allows the execution of external programs and commands. In this case, it's used to run system commands related to updating the operating system.
  3. Creating a Temporary File:

    QTemporaryFile* file = new QTemporaryFile(this);
    file->open();
    file->setAutoRemove(true);
    • A temporary file is created using QTemporaryFile. Temporary files are useful for storing temporary data that doesn't need to persist beyond the current session or task.
    • The file is opened for use, and the setAutoRemove(true) call ensures that the file will be automatically deleted once it's no longer needed (when it's closed).
  4. Launching the Update Command:

    process->start("/usr/lib/snigdhaos/launch-terminal", 
                    QStringList() << QString("sudo pacman -Syyu 2>&1 && rm \"" + file->fileName() + "\"; read -p 'Press Enter↵ to Exit'"));
    • This line starts a new process that will execute a shell command.
    • The command being executed is:
      • sudo pacman -Syyu: This is an Arch Linux package manager command to update the system. -Syyu forces a full refresh of the package database and upgrades all outdated packages.
      • 2>&1: This redirects standard error (stderr) to standard output (stdout), so both the error and output messages can be captured in one stream.
      • && rm \"" + file->fileName() + "\": This part deletes the temporary file after the update finishes.
      • read -p 'Press Enter↵ to Exit': This part pauses the terminal process, asking the user to press Enter before the terminal window closes.
    • The launch-terminal utility (likely a custom script or binary) is used to invoke this process in a terminal window with elevated privileges (via sudo).
  5. Handling Process Completion:

    connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), 
            this, [this, process, file](int exitcode, QProcess::ExitStatus status) {
    • Here, a connection is made to the finished signal of the QProcess object. This signal is emitted when the process (in this case, the system update command) finishes execution.
    • The finished signal provides the exit code and status of the process.
    • A lambda function is used to handle this signal when it's emitted. This function will clean up the resources (delete the process and temporary file) and evaluate the outcome of the update.
  6. Cleaning Up Resources:

    process->deleteLater();
    file->deleteLater();
    • deleteLater() schedules the QProcess and QTemporaryFile objects for deletion after the event loop finishes processing. This ensures that resources are freed appropriately.
  7. Evaluating Update Success or Failure:

    if (exitcode == 0 && !file->exists()) {
        relaunchSelf("POST_UPDATE");
    } else {
        relaunchSelf("UPDATE_RETRY");
    }
    • The exit code of the process is checked. An exit code of 0 typically means the process was successful, while a non-zero exit code means there was an error.
    • The second condition checks if the temporary file no longer exists, which implies that the update process finished properly and the file was deleted successfully.
    • If both conditions are met, the application relaunches itself in a "POST_UPDATE" state, indicating a successful update.
    • If the conditions aren't met (i.e., the update failed or the file still exists), the application relaunches with the "UPDATE_RETRY" state, suggesting that the update should be retried.

Summary:

The doUpdate() function is responsible for triggering and managing the system update process. It performs the following tasks:

  1. It checks whether the application is in a self-update mode, and if so, it prevents further updates.
  2. It launches a terminal process to execute the system update command (pacman -Syyu), ensuring the user sees the terminal window and can interact with it.
  3. It monitors the update process and cleans up resources after completion.
  4. Based on the outcome (success or failure), it restarts the application with an appropriate state: either to indicate success or to prompt the user to retry the update.