Jump to content

TINU: The bootable macOS installer creation tool - Mac app


ITzTravelInTime
390 posts in this topic

Recommended Posts

@ITzTravelInTime great work for hackintosh users..merry Christmas

 

 

Great,Merry Christmas to all

 

I am very happy to see the spirit of Christmas here.

 

For italian guys thre is a new video of my app that will be automatically published tomorrow (i recorded it on dec 23) on my yt channel and also a new video in englesh coming in the next days. This is my small christmas gift for you, I hope that you will enjoy it.

  • Like 2
Link to comment
Share on other sites

Today a friend has also created a guide that uses TINU to create an usb installer for mac users: https://www.tecnogalaxy.it/blog/come-creare-chiavetta-di-installazione-macos-high-sierra/

 

It's in Italian, but i like to have everything that regards my app all in one place.

 

As I already told you, if you want to create your own tutorials that uses this app, fell free to do it and to link that tutorials here

  • Like 1
Link to comment
Share on other sites

Looks dang good :) I've got one question, though... As a user of an unsupported mac, could this tool be used to create installmedia that would install Sierra on this old workhorse?

 

this tool can be use to create install medias for any aim, you should check is it's possible to install sierra on your machine and how

  • Like 1
Link to comment
Share on other sites

News about the new English video, it's almost ready and tomorrow or Dec. 28 should be online, it's a simple video in which i explain how to use it to create an install media, it's just made for real mac users, if you need an hackintosh video or tutorial, i have simply to record another video in which i show also how to install clover on it.

 

For the next version of the app i am considering various designs for a new icon of the app, and i am also working to the details of the new parts of the UI to give to the entire app coherence and continuity in it's design.

  • Like 3
Link to comment
Share on other sites

The English video is out and published, here it is:

 

 

I hope you enjoy it, but i am not the best when it comes to speak English in person, but i have tried to explain everything is needed about my app in the video, obv the public target for this first video are mac users, proprably i will do another one in the future for hackintioshers and such.

  • Like 1
Link to comment
Share on other sites

Guys an announcement, i have the new icon for tinu, i choosed to change it because that sierra icon may let people to think that tis app is for sierra only, but i have created a more generic icon for it, and also the UI redesign process is going, i have modified some things to have a more coherent and continue experience, now i am working on details currently

 

PS: Today it's my birthday, from today i am 20 years old

  • Like 3
Link to comment
Share on other sites

Guys, work on tinu continues, i am working a lot on it, currently i am working on rewriting an optimizing some of the code. For example previously i was using for the usable drives scan, an interpretation of the output of

diskutil list

But with a simple arg i can get a plist output that can be better to use with the code:

diskutil list -plist

So i have rewritten the code that scans for the usable drives to do the scan from the plist data, and i have also implemented some functions that codes and decodes plist serialization, i have also used that new plist to extract some info from the installer app's info.plist file, like the version or the bundle name, to let some of the new features to work better (no spoiler about that new features, sorry), but i can say that the version number of the next release will be 2.0 PUBLIC and i am spending a lot of time working on it, some days i work on it until 3 or 4 am in the night.

 

I am trying also to contact some youtuber and influencers to let them to know my app and myabe they will talk about it to their public.

 

In the meantime the current release seems to work very well, but people with virtual machine are having problems because the mac app store does not downloads the full high sierra installer app, any suggestions to help that users? For now i told them to download the app elsewhere or to use other versions like sierra that are not affected by this problem, some times downloading all the latest updates to the virtual machine seems to fix it.

  • Like 2
Link to comment
Share on other sites

After a lot of work i finally managed to create a working code that installs clover with custom options, so i have resolved all the problems i was having with the clover options using the installer command and plist serialization, now i have a working code demo to give to you as an example, it's a command line tool (with some functions from the tinu) that installs clover using the specified options, you have to edit some variables to choose the clover pkg, the path to save the options file and the mount point of the target drive, and because the installer command needs sudo, you need to enter your password for sudo into the password variable, here is the file with all the code that you can take a look, needs to be improved, but at the time being it seems to work, so i hope that also other people can learn from that.

 

To see this code inside of tinu you have to wait, i will use it in a version after the 2.0, because it needs a lot of work to be added and the version 2.0 is almost ready, so i want to release it as soon as i can so you have a lot of new stuff to use and i can focus my work on adding things like clover support and other important stuff, i hope can understand, but clover support, means a lot of work to do and i am working on it.

 

I leave to do my test code to install clover using swift and with custom settings (that you can choose from the code)

//
//  main.swift
//  test clover
//
//  Created by ITzTravelInTime on 22/10/17.
//  Copyright © 2017-2018 ITzTravelInTime. All rights reserved.
//
import Cocoa

//items class

class choseItem{
    var id: String
    var title: String
    var description: String
    
    var isVisible: Bool
    var isSelected: Bool
    var isEnabled: Bool
    
    var parent: choseItem!
    
    init(){
        id = ""
        title = ""
        description = ""
        
        isEnabled = true
        isVisible = true
        isSelected = true
        parent = nil
    }
    
    init(itemID: String, itemTitle: String, itemDescription: String, itemIsVisible: Bool,itemIsSelected: Bool, itemIsEnabled: Bool, itemParent: choseItem!){
        id = itemID
        title = itemTitle
        description = itemDescription
        
        isVisible = itemIsVisible
        isSelected = itemIsSelected
        isEnabled = itemIsEnabled
        
        parent = itemParent
    }
}

//this function stars a process and then returs the objects needed to track it
public func startCommand(cmd : String, args : [String]) -> (process: Process, errorPipe: Pipe, outputPipe: Pipe) {
    let task = Process()
    let outpipe = Pipe()
    let errpipe = Pipe()
    
    //stars a process object and then return the outputs
    task.launchPath = cmd
    task.arguments = args
    task.standardOutput = outpipe
    task.standardError = errpipe
    task.launch()
    
    return (task, errpipe, outpipe)
}

//runs a process until it ends and then returs the outputs and the erros
public func runCommand(cmd : String, args : [String]) -> (output: [String], error: [String], exitCode: Int32) {
    var output : [String] = []
    var error : [String] = []
    var status = Int32()
    //runs a process object and then return the outputs
    
    let p = startCommand(cmd: cmd, args: args)
    
    p.process.waitUntilExit()
    let outdata = p.outputPipe.fileHandleForReading.readDataToEndOfFile()
    if var string = String(data: outdata, encoding: .utf8) {
        string = string.trimmingCharacters(in: .newlines)
        output = string.components(separatedBy: "\n")
    }
    
    let errdata = p.errorPipe.fileHandleForReading.readDataToEndOfFile()
    if var string = String(data: errdata, encoding: .utf8) {
        string = string.trimmingCharacters(in: .newlines)
        error = string.components(separatedBy: "\n")
    }
    
    status = p.process.terminationStatus
    
    return (output, error, status)
}

//executes a process until it ends end then returns only the output/error
fileprivate func getOutSimply(cmd: String, isErr: Bool) -> String{
    //ths function runs a command on the sh shell and it does return the output or the error produced
    var ret = [String]()
    
    if isErr{
        ret = runCommand(cmd: "/bin/sh", args: ["-c", cmd]).error
    }else{
        ret = runCommand(cmd: "/bin/sh", args: ["-c", cmd]).output
    }
    
    var rett = ""
    for r in ret{
        rett += r + "\n"
    }
    if !rett.isEmpty{
        rett.removeLast()
    }
    
    return rett
}

//specialized versions of the previous version:
public func getErr(cmd: String) -> String{
    //ths function runs a command on the sh shell and it does return the error output
    return getOutSimply(cmd: cmd, isErr: true)
}

public func getOut(cmd: String) -> String{
    //ths function runs a command on the sh shell and it does return the output
    return getOutSimply(cmd: cmd, isErr: false)
}

//plist serialization and deserialization
func decodeXML(xml: String) throws -> NSArray{
    return try PropertyListSerialization.propertyList(from: xml.data(using: .utf8)!, options: [], format: nil) as! NSArray
}

func codeXML(decoded: NSArray) throws -> String{
    let d = try PropertyListSerialization.data(fromPropertyList: decoded, format: .xml, options: 0)
    return String.init(data: d, encoding: .utf8)!
}

//converts bool to int and reverse
func stringIntToBool(_ value: String!) -> Bool!{
    switch value {
    case "0":
        return false
    case "1":
        return true
    default:
        return nil
    }
}

func boolToIntString(_ value: Bool) -> Int{
    if value{
        return 1
    }
    return 0
}

//get options from the xml and add options to the final xml
func getItem(childs: [String: Any], parent: choseItem!, target: inout [String: choseItem]){
    let a = childs["childItems"] as! NSArray
    for i in a{
        let e = (i as! [String: Any])
        
        if e["choiceIsVisible"] != nil && e["choiceIsSelected"] != nil && e["choiceIsEnabled"] != nil{
            let iv = stringIntToBool("\(e["choiceIsVisible"]!)")
            let iss = stringIntToBool("\(e["choiceIsSelected"]!)")
            let ie = stringIntToBool("\(e["choiceIsEnabled"]!)")
            
            if iv != nil && iss != nil && ie != nil{
                let item = choseItem(itemID: "\(e["choiceIdentifier"]!)", itemTitle: "\(e["choiceTitle"]!)", itemDescription: "\(e["choiceDescription"]!)", itemIsVisible: iv!, itemIsSelected: iss!, itemIsEnabled: ie!, itemParent: parent)
                target[item.id] = item
                let d = e["childItems"] as? NSArray
                if d != nil{
                    if d!.count > 0{
                        getItem(childs: e,parent: item, target: &target)
                    }
                }
            }
        }
    }
}

func createCustomizedXML(baseXML: NSArray, choiches: [String: choseItem]) -> NSArray!{
    if var copya = baseXML.copy() as? [Any]{
        for ii in 0...copya.count - 1{
            if var i = baseXML[ii] as? [String: Any]{
                if let atr = i["choiceAttribute"] as? String{
                    if atr == "selected"{
                        if let value = choiches[i["choiceIdentifier"] as! String]{
                            if value.isVisible{
                                i["attributeSetting"] = boolToIntString(value.isSelected)
                                copya[ii] = i as Any
                            }
                        }
                    }
                }
            }
        }
        return copya as NSArray
    }
    return nil
}

//variables

let drive = "/Volumes/Install macOS High Sierra" //target drive to install clover

let pkg = "/Users/itztravelintime/Desktop/Clover_v2.4k_r4259.pkg" //path to your clover pkg
let config = "/Users/itztravelintime/Desktop/options.plist" //path to the configuration file to use
let password = ""

var xmls = getOut(cmd: "installer -showChoiceChangesXML -pkg \"" + pkg + "\"") //gets xml data for the options to pass to the package
var xmlc = getOut(cmd: "installer -showChoicesXML -pkg \"" + pkg + "\" -lang en") //gets xml data for the options to show to the user

var items = [String: choseItem]()

do{
    
    //gets the options to show to the user
    let a = try decodeXML(xml: xmlc).firstObject as! [String: Any]
    
    print("xml data estracted")
    
    //insers the option in the array items, to allow to the program to use them better
    getItem(childs: a, parent: nil, target: &items)
    
    print("items extracted")
    
    //edit settings here
    items["UEFI.only"]?.isSelected = true //the key must be the id of the cover option, ids could be found in xmlc variable plist data
    items["Target.ESP"]?.isSelected = true
    
    print("items edited")
    
    /*
    for item in items{
        print("\(item.key): \(item.value.isSelected)")
    }*/
    
    let decodedl = try decodeXML(xml: xmls)
    
    print("List decoded")
    
    let applyedl = createCustomizedXML(baseXML: decodedl, choiches: items)
    
    print("Customization applyed")
    
    let coded = try codeXML(decoded: applyedl!)
    
    print("List encoded")
    
    FileManager.default.createFile(atPath: config, contents: coded.data(using: .utf8), attributes: [:])
    
    print("File saved\nWaiting clover installation ...")
    
    //try to install clover
    if password.isEmpty{
        print("Empty password, insert the correct one to use sudo, into the \"password\" variable")
    }else{
        print(getOut(cmd: "echo \"\(password)\" | sudo -S installer -pkg \"\(pkg)\" -applyChoiceChangesXML \"\(config)\" -verbose -allowUntrusted -lang en -target \"\(drive)\""))
    }
    print("Execution finished")
    
}catch let error{
    print(error)
}
  • Like 1
Link to comment
Share on other sites

Why not only create Window ( Do you whant Open Clover Package and install them ) ⇥ open the Clover Packages at the end of install drive proceed

User only have to install Clover with her choice
Your only have to integrate the Clover Package inside the Bundle
 
For real Mac User ( Do you whant Open Clover Package and install them ) NO  :D
Link to comment
Share on other sites

 

Why not only create Window ( Do you whant Open Clover Package and install them ) ⇥ open the Clover Packages at the end of install drive proceed

User only have to install Clover with her choice
Your only have to integrate the Clover Package inside the Bundle
 
For real Mac User ( Do you whant Open Clover Package and install them ) NO  :D

 

It's not that simple, because i have to make sure that the user installs clover in the proper way and on the target drive, and i want also to offer some preconfigured templates for clover options, to make the thing more easy for some users, and of course i will ask if the users wants to use the usb with a real mac or with an hackintosh, for the clover package, to not have problems i have decided to not integrate it inside of tinu, but to ask if download it from the internet (tinu will automatically download the latest version) or if you are off-line it will ask to you to open a copy of clover locally on your computer, i don't want to in include clover into the bundle of my app to not have to update the app every time a new version of clover is out and of course to not have issues with licenses and other stuff and to maintain the download of tinu of as light weight as i can, maybe i can integrate fakesmc and a couple of important kexts, but only the ones that do not requires to be updated frequently, but i think that for kexts i will ask to the user for them, i want that tinu is more like a guided usb creation process more than a thing that does everything automatically.

Link to comment
Share on other sites

I know what you want

I made several precompile Package on the pass ; the problem is if that not work people blame you.

if you let the users choose they will not blame you.  This is my suggestion :angel:

Clover is Open Source f you compile Clover and create your own package I think its not a probleme,correct me if im wrong.

Link to comment
Share on other sites

I know what you want

I made several precompile Package on the pass ; the problem is if that not work people blame you.

if you let the users choose they will not blame you.  This is my suggestion :angel:

Clover is Open Source f you compile Clover and create your own package I think its not a probleme,correct me if im wrong.

yes, sure, but i just want to use all the official stuff because i don't want to mess with that and i want something as close as i can to the manual vanilla method, so i have created this system that uses official packages and i want the application to manage the installation of clover, i want that clover will be always installed correctly by guiding the user to the correct settings to use for it's machine, but i will also leave a totally manual option that will let you to install clover totally manually, by selecting settings from tinu, or to not let tinu to install clover and leave this entirely to the user manually, don't worry, i will leave a lot of choice to the user, but just opening the clover pkg with the installer app is not noob friendly and that's why i want a system that manages clover installation, to help noobs that don't know what to do with clover setup, and of course leave also options to do it with more freedom for the expert users.

  • Like 1
Link to comment
Share on other sites

I understand but as a noobs will use one of your setups and it does not work at all whether it's a PC or a laptop, there will always be a great Hackintosh champion :P  who will tell him to download the Clover Packages and use it differently. .

Even if you have the best suggestions when it will not work, who will point You! There is nothing better than a good explanatory video on how to use Clover
Link to comment
Share on other sites

 

I understand but as a noobs will use one of your setups and it does not work at all whether it's a PC or a laptop, there will always be a great Hackintosh champion :P  who will tell him to download the Clover Packages and use it differently. .

Even if you have the best suggestions when it will not work, who will point You! There is nothing better than a good explanatory video on how to use Clover

 

Yes, but i try to do my beast and to guide the user as i can

  • Like 1
Link to comment
Share on other sites

Yes, but i try to do my beast and to guide the user as i can

If you believe that you are in the best direction, so made the things. If it does not work well you'll have to try it

Link to comment
Share on other sites

  • 2 weeks later...

Ok after a period of sickness and other stuff i am back with tinu development, i am currently working on optimizing and making shorted the code i am waiting for the feedback from the designer about the new ui, and i am also hunting as my bugs as i can, do you have suggestions for options for generic clover installation? i want to use some templates for some generic clover installation or let the user to choose manually the options to use for clover, but for the version that i am going to release now there will be no clover support yet, but it will be introduced in following versions

  • Like 1
Link to comment
Share on other sites

×
×
  • Create New...