func contentsOfCartfileResolved(pth string) (string, error) { content, err := fileutil.ReadStringFromFile(pth) if err != nil { return "", err } return content, nil }
func cocoapodsVersionFromPodfileLock(podfileLockPth string) (string, error) { content, err := fileutil.ReadStringFromFile(podfileLockPth) if err != nil { return "", err } return cocoapodsVersionFromPodfileLockContent(content), nil }
func readLocalisedRecentChanges(recentChangesDir string) (map[string]string, error) { recentChangesMap := map[string]string{} pattern := filepath.Join(recentChangesDir, "whatsnew-*-*") recentChangesPaths, err := filepath.Glob(pattern) if err != nil { return map[string]string{}, err } pattern = `whatsnew-(?P<local>.*-.*)` re := regexp.MustCompile(pattern) for _, recentChangesPath := range recentChangesPaths { matches := re.FindStringSubmatch(recentChangesPath) if len(matches) == 2 { lanugage := matches[1] content, err := fileutil.ReadStringFromFile(recentChangesPath) if err != nil { return map[string]string{}, err } recentChangesMap[lanugage] = content } } return recentChangesMap, nil }
func calabashAndroidVersionFromGemfileLock(gemfileLockPth string) (string, error) { content, err := fileutil.ReadStringFromFile(gemfileLockPth) if err != nil { return "", err } return calabashAndroidFromGemfileLockContent(content), nil }
// CheckIsSetupWasDoneForVersion ... func CheckIsSetupWasDoneForVersion(ver string) bool { configPth := getBitriseConfigVersionSetupFilePath() cont, err := fileutil.ReadStringFromFile(configPth) if err != nil { return false } return (cont == ver) }
func isCacheAvailable(srcDir string) (bool, error) { carthageDir := filepath.Join(srcDir, carthageDirName) if exist, err := pathutil.IsPathExists(carthageDir); err != nil { return false, err } else if !exist { return false, nil } buildDir := filepath.Join(carthageDir, buildDirName) if exist, err := pathutil.IsPathExists(buildDir); err != nil { return false, err } else if exist { pattern := filepath.Join(buildDir, "*") files, err := filepath.Glob(pattern) if err != nil { return false, err } if len(files) == 0 { return false, nil } } else { return false, nil } // read cahce cacheContent := "" cacheFilePth := filepath.Join(srcDir, carthageDirName, cacheFileName) if exist, err := pathutil.IsPathExists(cacheFilePth); err != nil { return false, err } else if exist { cacheContent, err = fileutil.ReadStringFromFile(cacheFilePth) if err != nil { return false, err } } else { return false, nil } swiftVersion, err := swiftVersion() if err != nil { return false, err } resolvedFilePath := filepath.Join(srcDir, resolvedFileName) resolved, err := contentsOfCartfileResolved(resolvedFilePath) if err != nil { return false, err } desiredCacheContent := fmt.Sprintf("--Swift version: %s --Swift version \n --%s: %s --%s", swiftVersion, resolvedFileName, resolved, resolvedFileName) return cacheContent == desiredCacheContent, nil }
func testResultLogContent(pth string) (string, error) { if exist, err := pathutil.IsPathExists(pth); err != nil { return "", fmt.Errorf("Failed to check if path (%s) exist, error: %s", pth, err) } else if !exist { return "", fmt.Errorf("test result not exist at: %s", pth) } content, err := fileutil.ReadStringFromFile(pth) if err != nil { return "", fmt.Errorf("Failed to read file (%s), error: %s", pth, err) } return content, nil }
func scanXamarinProject(cmd *cobra.Command, args []string) error { absExportOutputDirPath, err := initExportOutputDir() if err != nil { return printXamarinScanFinishedWithError("Failed to prepare Export directory: %s", err) } logOutput := "" xamarinCmd := xamarin.CommandModel{} if paramXamarinOutputLogFilePath != "" { xamLog, err := fileutil.ReadStringFromFile(paramXamarinOutputLogFilePath) if err != nil { return printXamarinScanFinishedWithError("Failed to read log from the specified log file, error: %s", err) } logOutput = xamLog } else { // --- Inputs --- // Xamarin Solution Path xamarinCmd.SolutionFilePath = paramXamarinSolutionFilePath if xamarinCmd.SolutionFilePath == "" { askText := `Please drag-and-drop your Xamarin Solution (` + colorstring.Green(".sln") + `) file here, and then hit Enter` fmt.Println() projpth, err := goinp.AskForPath(askText) if err != nil { return printXamarinScanFinishedWithError("Failed to read input: %s", err) } xamarinCmd.SolutionFilePath = projpth } log.Debugf("xamSolutionPth: %s", xamarinCmd.SolutionFilePath) xamSln, err := solution.New(xamarinCmd.SolutionFilePath, true) if err != nil { return printXamarinScanFinishedWithError("Failed to analyze Xamarin solution: %s", err) } log.Debugf("xamSln: %#v", xamSln) // filter only the iOS "app"" projects xamarinProjectsToChooseFrom := []project.Model{} for _, aXamarinProject := range xamSln.ProjectMap { switch aXamarinProject.ProjectType { case constants.ProjectTypeIOS, constants.ProjectTypeTvOS, constants.ProjectTypeMacOS: if aXamarinProject.OutputType == "exe" { // possible project xamarinProjectsToChooseFrom = append(xamarinProjectsToChooseFrom, aXamarinProject) } default: continue } } log.Debugf("len(xamarinProjectsToChooseFrom): %#v", len(xamarinProjectsToChooseFrom)) log.Debugf("xamarinProjectsToChooseFrom: %#v", xamarinProjectsToChooseFrom) // Xamarin Project selectedXamarinProject := project.Model{} { if len(xamarinProjectsToChooseFrom) < 1 { return printXamarinScanFinishedWithError( "No acceptable Project found in the provided Solution, or none can be used for iOS Archive.", ) } if paramXamarinProjectName != "" { // project specified via flag/param for _, aProj := range xamarinProjectsToChooseFrom { if paramXamarinProjectName == aProj.Name { selectedXamarinProject = aProj break } } if selectedXamarinProject.Name == "" { return printXamarinScanFinishedWithError( `Invalid Project specified (%s), either not found in the provided Solution or it can't be used for iOS "Archive for Publishing".`, paramXamarinProjectName) } } else { // no project CLI param specified if len(xamarinProjectsToChooseFrom) == 1 { selectedXamarinProject = xamarinProjectsToChooseFrom[0] } else { projectNames := []string{} for _, aProj := range xamarinProjectsToChooseFrom { projectNames = append(projectNames, aProj.Name) } fmt.Println() answerValue, err := goinp.SelectFromStrings( `Select the Project Name you use for "Archive for Publishing" (usually ends with ".iOS", e.g.: MyProject.iOS)?`, projectNames, ) if err != nil { return printXamarinScanFinishedWithError("Failed to select Project: %s", err) } log.Debugf("selected project: %v", answerValue) for _, aProj := range xamarinProjectsToChooseFrom { if answerValue == aProj.Name { selectedXamarinProject = aProj break } } } } } xamarinCmd.ProjectName = selectedXamarinProject.Name log.Debugf("xamarinCmd.ProjectName: %s", xamarinCmd.ProjectName) log.Debugf("selectedXamarinProject.Configs: %#v", selectedXamarinProject.Configs) // Xamarin Configuration Name selectedXamarinConfigurationName := "" { acceptableConfigs := []string{} for configName, aConfig := range selectedXamarinProject.Configs { if aConfig.Platform == "iPhone" { if aConfig.Configuration == "Release" { // ios & tvOS app acceptableConfigs = append(acceptableConfigs, configName) } } else if aConfig.Platform == "x86" { if aConfig.Configuration == "Release" || aConfig.Configuration == "Debug" { // MacOS app acceptableConfigs = append(acceptableConfigs, configName) } } } if len(acceptableConfigs) < 1 { return printXamarinScanFinishedWithError( `No acceptable Configuration found in the provided Solution and Project, or none can be used for iOS "Archive for Publishing".`, ) } if paramXamarinConfigurationName != "" { // configuration specified via flag/param for _, aConfigName := range acceptableConfigs { if paramXamarinConfigurationName == aConfigName { selectedXamarinConfigurationName = aConfigName break } } if selectedXamarinConfigurationName == "" { return printXamarinScanFinishedWithError( "Invalid Configuration specified (%s), either not found in the provided Solution and Project or it can't be used for iOS Archive.", paramXamarinConfigurationName) } } else { // no configuration CLI param specified if len(acceptableConfigs) == 1 { selectedXamarinConfigurationName = acceptableConfigs[0] } else { fmt.Println() answerValue, err := goinp.SelectFromStrings( `Select the Configuration Name you use for "Archive for Publishing" (usually Release|iPhone)?`, acceptableConfigs, ) if err != nil { return printXamarinScanFinishedWithError("Failed to select Configuration: %s", err) } log.Debugf("selected configuration: %v", answerValue) selectedXamarinConfigurationName = answerValue } } } if selectedXamarinConfigurationName == "" { return printXamarinScanFinishedWithError( `No acceptable Configuration found (it was empty) in the provided Solution and Project, or none can be used for iOS "Archive for Publishing".`, ) } xamarinCmd.ConfigurationName = selectedXamarinConfigurationName fmt.Println() fmt.Println() log.Println(`🔦 Running a Build, to get all the required code signing settings...`) xamLogOut, err := xamarinCmd.GenerateLog() logOutput = xamLogOut // save the xamarin output into a debug log file logOutputFilePath := filepath.Join(absExportOutputDirPath, "xamarin-build-output.log") { log.Infof(" 💡 "+colorstring.Yellow("Saving xamarin output into file")+": %s", logOutputFilePath) if logWriteErr := fileutil.WriteStringToFile(logOutputFilePath, logOutput); logWriteErr != nil { log.Errorf("Failed to save xamarin build output into file (%s), error: %s", logOutputFilePath, logWriteErr) } else if err != nil { log.Infoln(colorstring.Yellow("Please check the logfile (" + logOutputFilePath + ") to see what caused the error")) log.Infoln(colorstring.Red(`and make sure that you can "Archive for Publishing" this project from Xamarin!`)) fmt.Println() log.Infoln("Open the project: ", xamarinCmd.SolutionFilePath) log.Infoln(`And do "Archive for Publishing", after selecting the Configuration: `, xamarinCmd.ConfigurationName) fmt.Println() } } if err != nil { return printXamarinScanFinishedWithError("Failed to run xamarin build command: %s", err) } } codeSigningSettings, err := xamarinCmd.ScanCodeSigningSettings(logOutput) if err != nil { return printXamarinScanFinishedWithError("Failed to detect code signing settings: %s", err) } log.Debugf("codeSigningSettings: %#v", codeSigningSettings) return exportCodeSigningFiles("Xamarin Studio", absExportOutputDirPath, codeSigningSettings) }
func analyzeSolution(pth string, analyzeProjects bool) (Model, error) { absPth, err := pathutil.AbsPath(pth) if err != nil { return Model{}, fmt.Errorf("Failed to expand path (%s), error: %s", pth, err) } fileName := filepath.Base(absPth) ext := filepath.Ext(absPth) fileName = strings.TrimSuffix(fileName, ext) solution := Model{ Pth: absPth, Name: fileName, ConfigMap: map[string]string{}, ProjectMap: map[string]project.Model{}, } isSolutionConfigurationPlatformsSection := false isProjectConfigurationPlatformsSection := false solutionDir := filepath.Dir(absPth) content, err := fileutil.ReadStringFromFile(absPth) if err != nil { return Model{}, fmt.Errorf("failed to read solution (%s), error: %s", absPth, err) } scanner := bufio.NewScanner(strings.NewReader(content)) for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) // Projects if matches := regexp.MustCompile(solutionProjectsPattern).FindStringSubmatch(line); len(matches) == 5 { ID := strings.ToUpper(matches[1]) projectName := matches[2] projectID := strings.ToUpper(matches[4]) projectRelativePth := utility.FixWindowsPath(matches[3]) projectPth := filepath.Join(solutionDir, projectRelativePth) if strings.HasSuffix(projectPth, constants.CSProjExt) || strings.HasSuffix(projectPth, constants.SHProjExt) || strings.HasSuffix(projectPth, constants.FSProjExt) { project := project.Model{ ID: projectID, Name: projectName, Pth: projectPth, ConfigMap: map[string]string{}, Configs: map[string]project.ConfigurationPlatformModel{}, } solution.ProjectMap[projectID] = project } solution.ID = ID continue } // GlobalSection(SolutionConfigurationPlatforms) = preSolution if isSolutionConfigurationPlatformsSection { if match := regexp.MustCompile(solutionConfigurationPlatformsSectionEndPattern).FindString(line); match != "" { isSolutionConfigurationPlatformsSection = false continue } } if match := regexp.MustCompile(solutionConfigurationPlatformsSectionStartPattern).FindString(line); match != "" { isSolutionConfigurationPlatformsSection = true continue } if isSolutionConfigurationPlatformsSection { if matches := regexp.MustCompile(solutionConfigurationPlatformPattern).FindStringSubmatch(line); len(matches) == 5 { configuration := matches[1] platform := matches[2] mappedConfiguration := matches[3] mappedPlatform := matches[4] solution.ConfigMap[utility.ToConfig(configuration, platform)] = utility.ToConfig(mappedConfiguration, mappedPlatform) continue } } // GlobalSection(ProjectConfigurationPlatforms) = postSolution if isProjectConfigurationPlatformsSection { if match := regexp.MustCompile(projectConfigurationPlatformsSectionEndPattern).FindString(line); match != "" { isProjectConfigurationPlatformsSection = false continue } } if match := regexp.MustCompile(projectConfigurationPlatformsSectionStartPattern).FindString(line); match != "" { isProjectConfigurationPlatformsSection = true continue } if isProjectConfigurationPlatformsSection { if matches := regexp.MustCompile(projectConfigurationPlatformPattern).FindStringSubmatch(line); len(matches) == 6 { projectID := strings.ToUpper(matches[1]) solutionConfiguration := matches[2] solutionPlatform := matches[3] projectConfiguration := matches[4] projectPlatform := matches[5] if projectPlatform == "Any CPU" { projectPlatform = "AnyCPU" } project, found := solution.ProjectMap[projectID] if !found { return Model{}, fmt.Errorf("no project found with ID: %s", projectID) } project.ConfigMap[utility.ToConfig(solutionConfiguration, solutionPlatform)] = utility.ToConfig(projectConfiguration, projectPlatform) solution.ProjectMap[projectID] = project continue } } } if err := scanner.Err(); err != nil { return Model{}, err } if analyzeProjects { projectMap := map[string]project.Model{} for projectID, proj := range solution.ProjectMap { projectDefinition, err := project.New(proj.Pth) if err != nil { return Model{}, fmt.Errorf("failed to analyze project (%s), error: %s", proj.Pth, err) } projectDefinition.Name = proj.Name projectDefinition.Pth = proj.Pth projectDefinition.ConfigMap = proj.ConfigMap projectMap[projectID] = projectDefinition } solution.ProjectMap = projectMap } return solution, nil }
// WriteChangelog ... func WriteChangelog(commits, taggedCommits []git.CommitModel, config Config, append bool) error { newChangelog := generateChangelogContent(commits, taggedCommits, config.Release.Version) headerStr := "" footerStr := "" contentStr := "" // // Generate changelog header if config.Changelog.HeaderTemplate == "" && config.Changelog.FooterTemplate == "" { log.Debug() log.Debug("Write changelog WITHOUT header and footer template") } // Header if config.Changelog.HeaderTemplate != "" { log.Debug() log.Debug("Write changelog with header and footer template") headerTemplate := template.New("changelog_header").Funcs(changelogTemplateFuncMap) headerTemplate, err := headerTemplate.Parse(config.Changelog.HeaderTemplate) if err != nil { log.Fatalf("Failed to parse header template, error: %#v", err) } var headerBytes bytes.Buffer err = headerTemplate.Execute(&headerBytes, newChangelog) if err != nil { log.Fatalf("Failed to execute layout template, error: %#v", err) } headerStr = headerBytes.String() headerStr += "\n\n" + separator + "\n" } // Footer if config.Changelog.FooterTemplate != "" { footerTemplate := template.New("changelog_footer").Funcs(changelogTemplateFuncMap) footerTemplate, err := footerTemplate.Parse(config.Changelog.FooterTemplate) if err != nil { log.Fatalf("Failed to parse footer template, error: %#v", err) } var footerBytes bytes.Buffer err = footerTemplate.Execute(&footerBytes, newChangelog) if err != nil { log.Fatalf("Failed to execute footer template, error: %#v", err) } footerStr = footerBytes.String() footerStr = separator + "\n\n" + footerStr } log.Debug() log.Debug("Layout header: %s", headerStr) log.Debug("Layout footer: %s", footerStr) // // Generate changelog content changelogContentTemplateStr := ChangelogContentTemplate if config.Changelog.ContentTemplate != "" { changelogContentTemplateStr = config.Changelog.ContentTemplate } contentTemplate := template.New("changelog_content").Funcs(changelogTemplateFuncMap) contentTemplate, err := contentTemplate.Parse(changelogContentTemplateStr) if err != nil { log.Fatalf("Failed to parse content template, error: %#v", err) } var newContentBytes bytes.Buffer err = contentTemplate.Execute(&newContentBytes, newChangelog) if err != nil { log.Fatalf("Failed to execute template, error: %#v", err) } newContentStr := newContentBytes.String() newContentSplit := strings.Split(newContentStr, "\n") if len(newContentSplit) > 0 { newContentSplit = newContentSplit[0 : len(newContentSplit)-1] newContentStr = strings.Join(newContentSplit, "\n") } log.Debug() log.Debug("Content:") for _, line := range strings.Split(newContentStr, "\n") { log.Debug("%s", line) } // Join header and content if append { log.Debug() log.Debug("Previous changelog exist, append new conent") prevChangelogStr, err := fileutil.ReadStringFromFile(config.Changelog.Path) if err != nil { return err } prevContentStr := "" if config.Changelog.HeaderTemplate != "" && config.Changelog.FooterTemplate != "" { tmpPrevContentStr, err := parseChangelog(prevChangelogStr) if err != nil { log.Warnf("Failed to parse previous changelog: %s", err) } else { prevContentStr = tmpPrevContentStr } } else { prevContentStr = prevChangelogStr } log.Debug() log.Debug("Prev content:") for _, line := range strings.Split(prevContentStr, "\n") { log.Debugf("%s", line) } contentStr = fmt.Sprintf("%s\n%s", newContentStr, prevContentStr) log.Debug() log.Debug("Merged content:") contentSplits := strings.Split(contentStr, "\n") for _, line := range contentSplits { log.Debugf("%s", line) } } else { log.Debug() log.Debug("NO previous changelog exist") contentStr = newContentStr } changelogStr := headerStr + "\n" + contentStr + "\n" + footerStr return fileutil.WriteStringToFile(config.Changelog.Path, changelogStr) }
func analyzeTargetDefinition(project Model, pth string) (Model, error) { configurationPlatform := ConfigurationPlatformModel{} isPropertyGroupSection := false isProjectReferenceSection := false projectDir := filepath.Dir(pth) projectDefinitionFileContent, err := fileutil.ReadStringFromFile(pth) if err != nil { return Model{}, fmt.Errorf("failed to read project (%s), error: %s", pth, err) } scanner := bufio.NewScanner(strings.NewReader(projectDefinitionFileContent)) for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) // Target definition if matches := regexp.MustCompile(targetDefinitionPattern).FindStringSubmatch(line); len(matches) == 2 { targetDefinitionRelativePth := utility.FixWindowsPath(matches[1]) if !strings.Contains(targetDefinitionRelativePth, "$(MSBuild") { targetDefinitionPth := filepath.Join(projectDir, targetDefinitionRelativePth) if exist, err := pathutil.IsPathExists(targetDefinitionPth); err != nil { return Model{}, err } else if exist { proj, err := analyzeTargetDefinition(project, targetDefinitionPth) if err != nil { return Model{}, err } project = proj } } continue } // ProjectGuid if matches := regexp.MustCompile(guidPattern).FindStringSubmatch(line); len(matches) == 2 { project.ID = matches[1] continue } // OutputType if matches := regexp.MustCompile(outputTpyePattern).FindStringSubmatch(line); len(matches) == 2 { project.OutputType = strings.ToLower(matches[1]) continue } // AssemblyName if matches := regexp.MustCompile(assemblyNamePattern).FindStringSubmatch(line); len(matches) == 2 { project.AssemblyName = matches[1] continue } // AndroidManifest if matches := regexp.MustCompile(manifestPattern).FindStringSubmatch(line); len(matches) == 2 { manifestRelativePth := utility.FixWindowsPath(matches[1]) project.ManifestPth = filepath.Join(projectDir, manifestRelativePth) continue } // AndroidApplication if match := regexp.MustCompile(androidApplicationPattern).FindString(line); match != "" { project.AndroidApplication = true continue } // // PropertyGroups if isPropertyGroupSection { if match := regexp.MustCompile(propertyGroupEndPattern).FindString(line); match != "" { project.Configs[utility.ToConfig(configurationPlatform.Configuration, configurationPlatform.Platform)] = configurationPlatform configurationPlatform = ConfigurationPlatformModel{} isPropertyGroupSection = false continue } } // PropertyGroup with Condition (Configuration & Platform) if matches := regexp.MustCompile(propertyGroupWithConditionConfigurationAndPlatformPattern).FindStringSubmatch(line); len(matches) == 3 { platform := matches[2] /* if platform == "AnyCPU" { platform = "Any CPU" } */ configurationPlatform = ConfigurationPlatformModel{ Configuration: matches[1], Platform: platform, } isPropertyGroupSection = true continue } // PropertyGroup with Condition (Configuration) if matches := regexp.MustCompile(propertyGroupWithConditionConfigurationPattern).FindStringSubmatch(line); len(matches) == 2 { configurationPlatform = ConfigurationPlatformModel{ Configuration: matches[1], } isPropertyGroupSection = true continue } // PropertyGroup with Condition (Platform) if matches := regexp.MustCompile(propertyGroupWithConditionPlatformPattern).FindStringSubmatch(line); len(matches) == 2 { platform := matches[2] /* if platform == "AnyCPU" { platform = "Any CPU" } */ configurationPlatform = ConfigurationPlatformModel{ Platform: platform, } isPropertyGroupSection = true continue } if isPropertyGroupSection { // OutputPath if matches := regexp.MustCompile(outputPathPattern).FindStringSubmatch(line); len(matches) == 2 { outputRelativePth := utility.FixWindowsPath(matches[1]) strings.Replace(outputRelativePth, "$(Configuration)", configurationPlatform.Configuration, -1) strings.Replace(outputRelativePth, "$(Platform)", configurationPlatform.Platform, -1) configurationPlatform.OutputDir = filepath.Join(projectDir, outputRelativePth) continue } // MtouchArch if matches := regexp.MustCompile(mtouchArchPattern).FindStringSubmatch(line); len(matches) == 2 { configurationPlatform.MtouchArchs = utility.SplitAndStripList(matches[1], ",") continue } // AndroidKeyStore if match := regexp.MustCompile(androidKeystorePattern).FindString(line); match != "" { configurationPlatform.SignAndroid = true continue } /* // IpaPackageName if match := regexp.MustCompile(ipaPackageNamePattern).FindString(line); match != "" { configurationPlatform.IpaPackage = true continue } */ // BuildIpa ... if match := regexp.MustCompile(buildIpaPattern).FindString(line); match != "" { configurationPlatform.BuildIpa = true continue } } // // API // ProjectTypeGuids if matches := regexp.MustCompile(typeGUIDsPattern).FindStringSubmatch(line); len(matches) == 2 { projectType := constants.ProjectTypeUnknown projectTypeList := strings.Split(matches[1], ";") for _, guid := range projectTypeList { guid = strings.TrimPrefix(guid, "{") guid = strings.TrimSuffix(guid, "}") projectType, err = constants.ParseProjectTypeGUID(guid) if err == nil { break } } project.ProjectType = projectType continue } if match := regexp.MustCompile(referenceXamarinUITestPattern).FindString(line); match != "" { project.TestFramworks = append(project.TestFramworks, constants.XamarinUITest) continue } if match := regexp.MustCompile(referenceNunitFramework).FindString(line); match != "" { project.TestFramworks = append(project.TestFramworks, constants.NunitTest) continue } if match := regexp.MustCompile(referenceNunitLiteFramework).FindString(line); match != "" { project.TestFramworks = append(project.TestFramworks, constants.NunitLiteTest) continue } // // ProjectReference if isProjectReferenceSection { if match := regexp.MustCompile(projectRefernceEndPattern).FindString(line); match != "" { isProjectReferenceSection = false } } // ProjectReference if matches := regexp.MustCompile(projectRefernceStartPattern).FindStringSubmatch(line); len(matches) == 2 { /* projectRelativePth := fixWindowsPath(matches[1]) projectPth := filepath.Join(projectDir, projectRelativePth) */ isProjectReferenceSection = true continue } if isProjectReferenceSection { if matches := regexp.MustCompile(referredProjectIDPattern).FindStringSubmatch(line); len(matches) == 2 { project.ReferredProjectIDs = append(project.ReferredProjectIDs, matches[1]) } continue } } if err := scanner.Err(); err != nil { return Model{}, err } return project, nil }
func scanXcodeProject(cmd *cobra.Command, args []string) error { absExportOutputDirPath, err := initExportOutputDir() if err != nil { return printXcodeScanFinishedWithError("Failed to prepare Export directory: %s", err) } xcodebuildOutput := "" xcodeCmd := xcode.CommandModel{} if paramXcodebuildOutputLogFilePath != "" { xcLog, err := fileutil.ReadStringFromFile(paramXcodebuildOutputLogFilePath) if err != nil { return printXcodeScanFinishedWithError("Failed to read log from the specified log file, error: %s", err) } xcodebuildOutput = xcLog } else { projectPath := paramXcodeProjectFilePath if projectPath == "" { askText := `Please drag-and-drop your Xcode Project (` + colorstring.Green(".xcodeproj") + `) or Workspace (` + colorstring.Green(".xcworkspace") + `) file, the one you usually open in Xcode, then hit Enter. (Note: if you have a Workspace file you should most likely use that)` fmt.Println() projpth, err := goinp.AskForPath(askText) if err != nil { return printXcodeScanFinishedWithError("Failed to read input: %s", err) } projectPath = projpth } log.Debugf("projectPath: %s", projectPath) xcodeCmd.ProjectFilePath = projectPath schemeToUse := paramXcodeScheme if schemeToUse == "" { fmt.Println() fmt.Println() log.Println("🔦 Scanning Schemes ...") schemes, err := xcodeCmd.ScanSchemes() if err != nil { return printXcodeScanFinishedWithError("Failed to scan Schemes: %s", err) } log.Debugf("schemes: %v", schemes) fmt.Println() selectedScheme, err := goinp.SelectFromStrings("Select the Scheme you usually use in Xcode", schemes) if err != nil { return printXcodeScanFinishedWithError("Failed to select Scheme: %s", err) } log.Debugf("selected scheme: %v", selectedScheme) schemeToUse = selectedScheme } xcodeCmd.Scheme = schemeToUse fmt.Println() fmt.Println() log.Println("🔦 Running an Xcode Archive, to get all the required code signing settings...") xcLog, err := xcodeCmd.GenerateLog() xcodebuildOutput = xcLog // save the xcodebuild output into a debug log file xcodebuildOutputFilePath := filepath.Join(absExportOutputDirPath, "xcodebuild-output.log") { log.Infof(" 💡 "+colorstring.Yellow("Saving xcodebuild output into file")+": %s", xcodebuildOutputFilePath) if logWriteErr := fileutil.WriteStringToFile(xcodebuildOutputFilePath, xcodebuildOutput); logWriteErr != nil { log.Errorf("Failed to save xcodebuild output into file (%s), error: %s", xcodebuildOutputFilePath, logWriteErr) } else if err != nil { log.Infoln(colorstring.Yellow("Please check the logfile (" + xcodebuildOutputFilePath + ") to see what caused the error")) log.Infoln(colorstring.Red("and make sure that you can Archive this project from Xcode!")) fmt.Println() log.Infoln("Open the project:", xcodeCmd.ProjectFilePath) log.Infoln("and Archive, using the Scheme:", xcodeCmd.Scheme) fmt.Println() } } if err != nil { return printXcodeScanFinishedWithError("Failed to run Xcode Archive: %s", err) } } codeSigningSettings, err := xcodeCmd.ScanCodeSigningSettings(xcodebuildOutput) if err != nil { return printXcodeScanFinishedWithError("Failed to detect code signing settings: %s", err) } log.Debugf("codeSigningSettings: %#v", codeSigningSettings) return exportCodeSigningFiles("Xcode", absExportOutputDirPath, codeSigningSettings) }