createInstance function

Future<void> createInstance(
  1. TextEditingController nameController,
  2. TextEditingController locationController,
  3. WSLApi api,
  4. TextEditingController autoSuggestBox,
  5. TextEditingController userController
)

Implementation

Future<void> createInstance(
  TextEditingController nameController,
  TextEditingController locationController,
  WSLApi api,
  TextEditingController autoSuggestBox,
  TextEditingController userController,
) async {
  plausible.event(name: "wsl_create");
  String label = nameController.text;
  // Replace all special characters with _
  String name = label.replaceAll(RegExp('[^A-Za-z0-9]'), '_');
  if (name != '') {
    String distroName = autoSuggestBox.text;

    // Set paths
    Notify.message('creatinginstance-text'.i18n(), loading: true);
    String location = locationController.text;
    if (location == '') {
      location = prefs.getString("DistroPath") ?? defaultPath;
      location += '/$name';
    }

    // Check if docker image
    bool isDockerImage = false;
    if (distroName.startsWith('dockerhub:')) {
      isDockerImage = true;
      // Remove prefix
      distroName = autoSuggestBox.text.split('dockerhub:')[1];
      // Get tag
      if (!distroName.contains(':')) {
        distroName += ':latest';
      }
      String? image = distroName.split(':')[0];
      String? tag = distroName.split(':')[1];

      if (!distroName.contains('/')) {
        image = 'library/$image';
      }

      bool isDownloaded = false;
      // Check if image already downloaded
      if (await DockerImage().isDownloaded(image, tag: tag)) {
        isDownloaded = true;
      }

      // Check if image exists
      if (!isDownloaded && await DockerImage().hasImage(image, tag: tag)) {
        // Download image
        Notify.message('${'downloading-text'.i18n()}...');
        var docker = DockerImage()..distroName = distroName;
        await docker.getRootfs(name, image, tag: tag,
            progress: (current, total, currentStep, totalStep) {
          if (currentStep != -1) {
            String progressInMB =
                (currentStep / 1024 / 1024).toStringAsFixed(2);
            // String totalInMB = (total / 1024 / 1024).toStringAsFixed(2);
            String percentage =
                (currentStep / totalStep * 100).toStringAsFixed(0);
            Notify.message('${'downloading-text'.i18n()}'
                ' Layer ${current + 1}/$total: $percentage% ($progressInMB MB)');
          } else {
            Notify.message(
                'extractinglayers-text'.i18n(['$current', '$total']));
          }
        });
        Notify.message('downloaded-text'.i18n());
        // Set distropath with distroName
        distroName = DockerImage().filename(image, tag);
      } else if (!isDownloaded) {
        Notify.message('distronotfound-text'.i18n());
        return;
      }

      if (isDownloaded) {
        // Set distropath with distroName
        distroName = DockerImage().filename(image, tag);
      }
    }

    // Navigator.of(context, rootNavigator: true).pop();

    // Create instance
    ProcessResult result = await api.create(
        name, distroName, location, (String msg) => Notify.message(msg),
        image: isDockerImage);

    // Check if instance was created then handle postprocessing
    if (result.exitCode != 0) {
      Notify.message(WSLApi().utf8Convert(result.stdout));
    } else {
      var userCmds = prefs.getStringList('UserCmds_$distroName');
      var groupCmds = prefs.getStringList('GroupCmds_$distroName');
      if (userCmds != null && groupCmds != null) {
        for (int i = 0; i < groupCmds.length; i++) {
          var cmd = groupCmds[i].replaceAll("/bin/sh -c ", "");
          cmd = cmd.replaceAll(RegExp(r'\s+'), ' ');
          await api.exec(name, [cmd]);
        }
        for (int i = 0; i < userCmds.length; i++) {
          var cmd = userCmds[i].replaceAll("/bin/sh -c ", "");
          // Replace multiple spaces with one
          cmd = cmd.replaceAll(RegExp(r'\s+'), ' ');
          await api.exec(name, [cmd]);
        }
      }
      String user = userController.text;
      if (user != '') {
        List<int> processes = await api.exec(name, [
          'apt-get update',
          'apt-get install -y sudo',
          'useradd -m -s /bin/bash -G sudo $user',
          'passwd $user',
          'echo \'$user ALL=(ALL) NOPASSWD:ALL\' >> /etc/sudoers.d/wslsudo',
          'echo -e \'[user]\ndefault = $user\' > /etc/wsl.conf',
        ]);
        bool success = true;
        for (dynamic process in processes) {
          if (process != 0) {
            success = false;
            break;
          }
        }
        if (success) {
          prefs.setString('StartPath_$name', '/home/$user');
          prefs.setString('StartUser_$name', user);

          Notify.message('createdinstance-text'.i18n());
        } else {
          Notify.message('createdinstancenouser-text'.i18n());
        }
      } else {
        // Install fake systemctl
        if (distroName.contains('Turnkey')) {
          // Set first start variable
          prefs.setBool('TurnkeyFirstStart_$name', true);
          Notify.message('installingfakesystemd-text'.i18n(), loading: true);
          WSLApi().execCmds(
              name,
              [
                'wget https://raw.githubusercontent.com/bostrot/'
                    'fake-systemd/master/systemctl -O /usr/bin/systemctl',
                'chmod +x /usr/bin/systemctl',
                '/usr/bin/systemctl',
              ],
              onMsg: (output) => null,
              onDone: () => Notify.message('createdinstance-text'.i18n()));
        } else {
          Notify.message('createdinstance-text'.i18n());
        }
      }
      // Save distro label
      prefs.setString('DistroName_$name', label);
      // Save distro path
      prefs.setString('Path_$name', location);
    }
    // Download distro check
  } else {
    Notify.message('entername-text'.i18n());
  }
}