Kyle Decot
Kyle Decot

Reputation: 20815

How to Check if Xcode License Needs to be Accepted

After upgrading to Xcode 11.1 on MacOS Catalina running some commands such as git status results in Xcode stating that a license must be agreed to. Obviously we could run git status and grep for some output but this seems sub-optimal.

Is there a programmatic way (using xcodebuild for example) to check if the Xcode license needs to be accepted?

Upvotes: 4

Views: 1212

Answers (1)

Stephan Schlecht
Stephan Schlecht

Reputation: 27126

Evaluate Agreed License

Running

defaults read /Library/Preferences/com.apple.dt.Xcode

should give something like:

{
    IDELastGMLicenseAgreedTo = EA1647;
    IDEXcodeVersionForAgreedToGMLicense = "11.3.1";
}

This can also be evaluated programmatically.

There are several ways to do this, one is to use a shell script, for example you could call it XcodeLicenseAccepted.sh and it will return 0 if the license for the currently installed version of Xcode is already accepted.

Xcode version

To get the version number of the currently installed Xcode, you can take a look at the output of:

xcodebuild -version 

which should look something like this:

Xcode 11.3.1
Build version 11C505

XcodeLicenseAccepted.sh

#!/bin/sh
XCODE_VERSION=`xcodebuild -version | grep '^Xcode\s' | sed -E 's/^Xcode[[:space:]]+([0-9\.]+)/\1/'`
ACCEPTED_LICENSE_VERSION=`defaults read /Library/Preferences/com.apple.dt.Xcode 2> /dev/null | grep IDEXcodeVersionForAgreedToGMLicense | cut -d '"' -f 2`

if [ "$XCODE_VERSION" = "$ACCEPTED_LICENSE_VERSION" ]
then 
    exit 0 #success
else
    exit 1
fi

Swift Program

Another possible solution would be to use a small Swift program instead, e.g.:

import Foundation

private var acceptedXcodeVersion: String {
    var acceptedXcodeVersion = ""
    let licensePlistPath = "/Library/Preferences/com.apple.dt.Xcode.plist"
    if FileManager.default.fileExists(atPath: licensePlistPath) {
        if let licenseInfo = NSDictionary(contentsOfFile: licensePlistPath) {
            if let version = licenseInfo["IDEXcodeVersionForAgreedToGMLicense"] as? String {
                acceptedXcodeVersion = version
            }
        }
    }
    return acceptedXcodeVersion
}

private var installedXcodeVersion: String {
    let process = Process()
    process.launchPath = "/bin/sh"
    process.arguments = ["-c", "xcodebuild -version"]

    let stdoutPipe = Pipe()
    process.standardOutput = stdoutPipe
    process.launch()

    var version = ""
    let output = stdoutPipe.fileHandleForReading.readDataToEndOfFile()
    if let versionInfo = String(data: output, encoding: .utf8) {
        let lines = versionInfo.split { $0.isNewline }
        for line in lines {
            let parts = line.split { $0 == " " }
            if parts.count > 1 && parts[0] == "Xcode" {
                version = String(parts[1])
            }
        }
    }

    process.waitUntilExit()
    return version
}

exit(acceptedXcodeVersion == installedXcodeVersion ?  0 : 1)

Test

To demo the functionality of XcodeLicenseAccepted.sh one can also use a short shell script:

#!/bin/sh

./XcodeLicenseAccepted.sh
if [ $? -eq 0 ]
then 
    echo "xcode license already accepted"
else
    echo "xcode license still needs to be accepted"
fi

Replace the call to XcodeLicenseAccepted.sh with the Swift program to test the alternative solution.

Finally a screenshot how the result looks before and after accepting the Xcode license:

demo output

Upvotes: 8

Related Questions