func writeIdentities(identites []byte, absExportOutputDirPath string) error {
	return ioutil.WriteFile(filepath.Join(absExportOutputDirPath, "Identities.p12"), identites, 0600)
}
writeIdentities writes identities to a file path
package codesign
import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"github.com/bitrise-io/codesigndoc/bitriseio"
	"github.com/bitrise-io/codesigndoc/bitriseio/bitrise"
	"github.com/bitrise-io/codesigndoc/models"
	"github.com/bitrise-io/codesigndoc/osxkeychain"
	"github.com/bitrise-io/codesigndoc/utility"
	"github.com/bitrise-io/go-utils/log"
	"github.com/bitrise-io/go-xcode/certificateutil"
	"github.com/bitrise-io/go-xcode/profileutil"
	"github.com/bitrise-io/goinp/goinp"
)
type UploadConfig struct {
	PersonalAccessToken string
	AppSlug             string
}
type WriteFilesConfig struct {
	WriteFiles       WriteFilesLevel
	AbsOutputDirPath string
}
type WriteFilesLevel int
const (
	Invalid WriteFilesLevel = iota
	WriteFilesAlways
	WriteFilesFallback
	WriteFilesDisabled
)
type ExportReport struct {
	CertificatesUploaded         bool
	ProvisioningProfilesUploaded bool
	CodesignFilesWritten         bool
}
func ExportCodesigningFiles(certificatesRequired []certificateutil.CertificateInfoModel, profilesRequired []profileutil.ProvisioningProfileInfoModel, askForPassword bool) (models.Certificates, []models.ProvisioningProfile, error) {
	certificates, err := exportIdentities(certificatesRequired, askForPassword)
	if err != nil {
		return models.Certificates{}, nil, err
	}
	profiles, err := exportProvisioningProfiles(profilesRequired)
	if err != nil {
		return models.Certificates{}, nil, err
	}
	return certificates, profiles, nil
}
func UploadAndWriteCodesignFiles(certificates models.Certificates, provisioningProfiles []models.ProvisioningProfile, writeFilesConfig WriteFilesConfig, uploadConfig UploadConfig) (ExportReport, error) {
	var client *bitrise.Client
	if uploadConfig.PersonalAccessToken != "" && uploadConfig.AppSlug != "" {
		var err error
		client, err = bitrise.NewClient(uploadConfig.PersonalAccessToken)
		if err != nil {
			return ExportReport{}, err
		}
		client.SetSelectedAppSlug(uploadConfig.AppSlug)
	}
	if client == nil {
		uploadConfirmMsg := "Do you want to upload the provisioning profiles and certificates to Bitrise?"
		if len(provisioningProfiles) == 0 {
			uploadConfirmMsg = "Do you want to upload the certificates to Bitrise?"
		}
		fmt.Println()
		shouldUpload, err := goinp.AskForBoolFromReader(uploadConfirmMsg, os.Stdin)
		if err != nil {
			return ExportReport{}, err
		}
		if shouldUpload {
			if client, err = bitriseio.GetInteractiveConfigClient(); err != nil {
				return ExportReport{}, err
			}
		}
	}
	var filesWritten bool
	if writeFilesConfig.WriteFiles == WriteFilesAlways ||
		writeFilesConfig.WriteFiles == WriteFilesFallback && client == nil {
		if err := writeFiles(certificates, provisioningProfiles, writeFilesConfig); err != nil {
			return ExportReport{}, err
		}
		filesWritten = true
	}
	if client == nil {
		return ExportReport{
			CertificatesUploaded:         len(certificates.Info) == 0,
			ProvisioningProfilesUploaded: len(provisioningProfiles) == 0,
			CodesignFilesWritten:         filesWritten,
		}, nil
	}
	certificatesUploaded, profilesUploaded, err := bitriseio.UploadCodesigningFiles(client, certificates, provisioningProfiles)
	return ExportReport{
		CertificatesUploaded:         certificatesUploaded,
		ProvisioningProfilesUploaded: profilesUploaded,
		CodesignFilesWritten:         filesWritten,
	}, err
}
func writeFiles(identities models.Certificates, provisioningProfiles []models.ProvisioningProfile, writeFilesConfig WriteFilesConfig) error {
	if err := os.MkdirAll(writeFilesConfig.AbsOutputDirPath, 0700); err != nil {
		return fmt.Errorf("failed to create output directory for codesigning files, error: %s", err)
	}
	entries, err := ioutil.ReadDir(writeFilesConfig.AbsOutputDirPath)
	if err != nil && err != os.ErrNotExist {
		return fmt.Errorf("failed to check output directory contents, error: %s", err)
	}
	containsArtifacts := false
	for _, entry := range entries {
		if !entry.IsDir() && (path.Ext(entry.Name()) != ".log") {
			containsArtifacts = true
			break
		}
	}
	if containsArtifacts {
		fmt.Println()
		log.Warnf("Export output directory exists and is not empty.")
	}
	if err := writeIdentities(identities.Content, writeFilesConfig.AbsOutputDirPath); err != nil {
		return err
	}
	if err := writeProvisioningProfiles(provisioningProfiles, writeFilesConfig.AbsOutputDirPath); err != nil {
		return err
	}
	return nil
}
func exportIdentities(certificates []certificateutil.CertificateInfoModel, isAskForPassword bool) (models.Certificates, error) {
	if len(certificates) == 0 {
		return models.Certificates{}, nil
	}
	fmt.Println()
	fmt.Println()
	log.Infof("Required Identities/Certificates (%d)", len(certificates))
	for _, certificate := range certificates {
		log.Printf("- %s", certificate.CommonName)
	}
	fmt.Println()
	log.Infof("Exporting the Identities (Certificates):")
	identitiesWithKeychainRefs := []osxkeychain.IdentityWithRefModel{}
	defer osxkeychain.ReleaseIdentityWithRefList(identitiesWithKeychainRefs)
	for _, certificate := range certificates {
		log.Printf("searching for Identity: %s", certificate.CommonName)
		identityRef, err := osxkeychain.FindAndValidateIdentity(certificate.CommonName)
		if err != nil {
			return models.Certificates{}, fmt.Errorf("failed to export, error: %s", err)
		}
		if identityRef == nil {
			return models.Certificates{}, errors.New("identity not found in the keychain, or it was invalid (expired)")
		}
		identitiesWithKeychainRefs = append(identitiesWithKeychainRefs, *identityRef)
	}
	identityKechainRefs := osxkeychain.CreateEmptyCFTypeRefSlice()
	for _, aIdentityWithRefItm := range identitiesWithKeychainRefs {
		fmt.Println("exporting Identity:", aIdentityWithRefItm.Label)
		identityKechainRefs = append(identityKechainRefs, aIdentityWithRefItm.KeychainRef)
	}
	fmt.Println()
	if isAskForPassword {
		log.Infof("Exporting from Keychain")
		log.Warnf(" You'll be asked to provide a Passphrase for the .p12 file!")
	} else {
		log.Warnf("Exporting from Keychain using empty Passphrase...")
		log.Printf("This means that if you want to import the file the passphrase at import should be left empty,")
		log.Printf("you don't have to type in anything, just leave the passphrase input empty.")
	}
	fmt.Println()
	log.Warnf("You'll most likely see popups one for each Identity from Keychain,")
	log.Warnf("you will have to accept (Allow) those to be able to export the Identities!")
	fmt.Println()
	identities, err := osxkeychain.ExportFromKeychain(identityKechainRefs, isAskForPassword)
	if err != nil {
		return models.Certificates{}, fmt.Errorf("failed to export from Keychain: %s", err)
	}
	return models.Certificates{
		Info:    certificates,
		Content: identities,
	}, nil
}